如何决定何时在表列上使用索引

时间:2012-08-16 09:50:27

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

我什么时候应该在桌子上使用索引?

  1. 从多少行索引有意义?
  2. 如果我有持续行的表,只是编辑过来的列(不在'where'子句中),即使表只有大约15行,也会使索引有意义吗?编辑:在这种情况下,非索引选择/阅读比索引读取更有效吗?
  3. 编辑: 现在我正在使用firebird 2.5,但大多数时候我使用的是SQL Server 2005/2008。

5 个答案:

答案 0 :(得分:29)

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

  • 选择良好群集密钥 - 不是GUID,而不是VARCHAR(250)或其他内容 - 良好群集密钥狭窄,独特,稳定,不断增加的 - 像INT IDENTITY这样的东西是完美的。使其成为您的群集主键 - >为您提供表格上的第一个索引

  • 对于任何用作外键的列到另一个表中 - 添加索引。它可以是单个列索​​引 - 或者它可能是复合索引 - 无论哪种方式最适合您的情况。重要的是外键列是该索引中的第一个列(如果您使用的是复合索引) - 否则,JOIN的好处或检查参照完整性将无法使用您的系统

现在就是这样。

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

如果没有:然后开始收集数据和指示,说明为什么应用程序不够快。看看例如像SQL Server中的DMV那样告诉你性能最差的查询,或缺少索引DMV 。分析那些。看看你可以改进什么。一次添加一个索引,然后再次:观察,测量,与基线进行比较。

如果你有改进 - >保留该指数,此测量值是您的新基线。冲洗并重复,直到您(和您的用户)对应用程序的性能感到满意为止(并且然后回家并享受休假)。

SQL Server中的过度索引可能比没有任何索引更差。不要从一开始就有太多的指数开始!只建立好的聚类PK和外键非聚集索引 - 这就是全部 - 然后观察,测量,优化和优化重复这个循环。

答案 1 :(得分:6)

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

你似乎是新问题,所以我建议你看看你的执行计划,并试图消除所有“扫描”操作,因为它们几乎读取所有表甚至所有索引。你应该总是寻找寻求,但你应该平衡你在桌子上的索引数量。

如果您使用的是SQL Server,则可以使用SQL Server分析器运行跟踪来帮助您

编辑:

  

在这种情况下可以比非索引选择/阅读更有效   索引读?

是的,但如果发生这种情况,引擎将足够智能,不使用索引

答案 2 :(得分:1)

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

有些人提到采用基线,使用某种跟踪效用来衡量绩效等。如果您对已建立的表现没有问题,请继续。如果没有,分析执行计划,物理数据模型(可用索引),重新计算统计数据,看看是否有助于优化器选择更好的执行计划。确保DBMS可以(允许)使用可用的RAM。尽量减少磁盘I / O等。

对于Firebird 2.5,新添加的Firebird Trace API是天赐之物。现在,您终于可以使用性能计数器(执行计划,执行时间,I / O统计信息......)近乎实时地跟踪对数据库执行的操作。由FB TraceManager称为Upscene Productions的第三方产品使Trace API成为一种乐趣。

答案 3 :(得分:0)

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

答案 4 :(得分:0)

我使用此查询来获取我的哪些表需要索引的线索:

-- 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);

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

相关问题