【问题标题】:How to decide when use index on table column如何决定何时在表列上使用索引
【发布时间】:2012-08-12 15:40:51
【问题描述】:

什么时候应该在表上使用索引?

  1. 从多少行索引才有意义?
  2. 如果我有固定行的表,只是编辑了列(不在“where”子句中),即使表只有大约 15 行,索引是否有意义?编辑:在这种情况下,非索引选择/读取是否比索引读取更有效?

编辑: 现在我正在使用 firebird 2.5,但大多数时候我使用的是 SQL Server 2005/2008。

【问题讨论】:

  • 什么数据库系统,哪个版本? SQL 只是 结构化查询语言 - 许多数据库系统使用的语言,但不是数据库产品...这样的功能通常是特定于供应商的 - 所以我们真的需要知道您使用的是什么数据库系统....
  • 我认为这是一个常见的问题,不太依赖于 sql 系统。但现在它被指定了。谢谢。
  • 如何以及何时应用索引高度取决于实际系统 - 这就是为什么我想知道您正在使用什么。
  • 好吧,你可能是对的。 :-)

标签: sql sql-server-2008 sql-server-2005 indexing firebird2.5


【解决方案1】:

一般来说,我的索引策略是这样的(我现在只使用 SQL Server - 根据需要适应您自己的数据库系统):

  • 选择一个 good 集群键 - 不是 GUID,不是 VARCHAR(250) 或其他东西 - good 集群键是窄的、唯一的,稳定,不断增加 - 像 INT IDENTITY 这样的东西是完美的。使其成为您的聚集主键 -> 为您提供表上的第一个索引

  • 对于被用作另一个表的外键的任何列 - 添加索引。它可以是单列索引 - 也可以是复合索引 - 最适合您的情况。重要的是外键列是该索引中的 first 列(如果您使用的是复合索引) - 否则,JOIN 或检查参照完整性的好处将不会’对您的系统不可用

到此为止。

然后:运行您的系统 - 观察和测量 - 建立基线。应用程序是否足够快?如果是 -> 你已经完成了 - 回家享受你的业余时间。

如果不是:则开始收集数据并说明应用程序运行速度不够快的原因。看看例如SQL Server 中的 DMV 之类的东西会告诉您性能最差的查询,或者 缺少索引 DMV。分析那些。看看你可以改进什么。 一次添加一个索引并重复:观察、测量、与您的基线进行比较。

如果您有改进 -> 保留该指数,该衡量标准就是您的新基准。冲洗并重复,直到您(和您的用户)对应用程序的性能感到满意(然后回家享受您的休息时间)。

SQL Server 中的过度索引可能比没有任何索引更糟糕。不要从太多的索引开始!只建立 good 聚簇 PK 和外键非聚簇索引 - 仅此而已 - 然后观察、测量、优化和重复该循环。

【讨论】:

  • +1 表示在基线测试之间一次进行一项更改。
【解决方案2】:

这是一个非常复杂的讨论,您必须牢记几件事。主要是你不应该根据表上的行数来考虑索引,而是根据你对它运行的查询来考虑。索引仅有助于选择查询,同时它会略微降低插入、删除和更新的性能,因为除了更改表上的行之外,您还必须更改索引。

您似乎对这件事很陌生,所以我建议您查看您的执行计划并尝试消除所有“扫描”操作,因为它们几乎读取所有表甚至所有索引。您应该始终保持搜索,但您应该与表上的索引数量保持平衡。

如果您使用的是 SQL Server,您可以使用 SQL Server profiler 运行跟踪以帮助您

编辑:

在这种情况下,非索引选择/读取比 索引读取?

是的,但如果发生这种情况,引擎会很聪明,不会使用索引

【讨论】:

    【解决方案3】:

    索引适用于从表中挑选一小部分行。按主键值查询是对索引的最佳利用。最糟糕的情况是通过索引访问表中的所有行,因为它必须读取索引页引用的数据页。另一个例子是结果集的内存排序可能比通过排序列上的索引对结果集进行排序更快。永远不要忘记,虽然索引可以提高查询性能,但索引会降低写入性能。

    有些人提到了建立基线,使用某种跟踪实用程序来衡量性能等。如果您对既定的性能感到满意,请继续。如果没有,分析执行计划,物理数据模型(可用索引),重新计算统计数据,看看是否有助于优化器选择更好的执行计划。确保 DBMS 可以(被允许)利用可用的 RAM。尽量减少磁盘 I/O 等等。

    对于 Firebird 2.5,新添加的 Firebird Trace API 是天赐之物。现在,您终于可以通过性能计数器(执行计划、执行时间、I/O 统计...)获得对数据库执行的近乎实时的跟踪。而由Upscene Productions 称为FB TraceManager 的第三方产品让Trace API 使用起来很有趣。

    【讨论】:

      【解决方案4】:

      关于你问题的第二部分,如果一个表只有 15 行,很可能无论你有多少索引,该表都会被扫描,因为它太小了。

      【讨论】:

        【解决方案5】:

        我使用此查询来了解我的哪些表需要索引:

        -- Missing Indexes for current database by Index Advantage  (Query 57) (Missing Indexes)
        SELECT DISTINCT CONVERT(decimal(18,2), user_seeks * avg_total_user_cost * (avg_user_impact * 0.01)) AS [index_advantage], 
        migs.last_user_seek, mid.[statement] AS [Database.Schema.Table],
        mid.equality_columns, mid.inequality_columns, mid.included_columns,
        migs.unique_compiles, migs.user_seeks, migs.avg_total_user_cost, migs.avg_user_impact,
        OBJECT_NAME(mid.[object_id]) AS [Table Name], p.rows AS [Table Rows]
        FROM sys.dm_db_missing_index_group_stats AS migs WITH (NOLOCK)
        INNER JOIN sys.dm_db_missing_index_groups AS mig WITH (NOLOCK)
        ON migs.group_handle = mig.index_group_handle
        INNER JOIN sys.dm_db_missing_index_details AS mid WITH (NOLOCK)
        ON mig.index_handle = mid.index_handle
        INNER JOIN sys.partitions AS p WITH (NOLOCK)
        ON p.[object_id] = mid.[object_id]
        WHERE mid.database_id = DB_ID() 
        ORDER BY index_advantage DESC OPTION (RECOMPILE);
        

        请注意,这只会给您一个北方,您仍然需要考虑上面已经回答的内容。

        【讨论】:

          猜你喜欢
          • 2011-12-06
          • 2019-10-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-06-23
          • 1970-01-01
          • 2019-04-29
          相关资源
          最近更新 更多