是否有必要在SQL表中的每个可查询字段组合上建立索引以优化性能?

时间:2011-07-27 20:57:19

标签: mysql sql database indexing

如果我的User表有几个可查询的字段(比如DepartmentId,GroupId,RoleId),如果我为这些字段的每个组合创建索引,它会产生任何速度差异吗?

通过“可查询”,我指的是一个查询屏幕,最终用户可以通过从下拉菜单中选择,根据部门,组或角色选择记录。

目前,我有一个关于DepartmentId,GroupId和RoleId的索引。这是每个字段的一个非唯一索引。

如果最终用户选择“B组中的任何人”,则SQL看起来像:

select * from User where GroupId = 2

拥有GroupId的索引应该加快速度。

但是如果最终用户选择“B组和角色C中的任何人”,则SQL将如下所示:

select * from User where GroupId = 2 and RoleId = 3

单独在GroupId和RoleId上建立索引可能没有任何区别,对吗?

如果我有一个索引跨越 GroupId和RoleId,那么该搜索的更好的索引就是。

但如果是这样的话,那就意味着我需要为可查询字段的每个组合都有一个索引。所以我需要所有这些索引:

  • DepartmentID的
  • 的GroupId
  • 角色ID
  • DepartmentId和GroupId
  • DepartmentId和RoleId
  • GroupId和RoleId
  • 部门ID,GroupId和RoleId

有人可以对此有所了解吗?如果有所作为,我正在使用MySQL。

6 个答案:

答案 0 :(得分:8)

多列索引可用于该索引的任何左前缀。因此,(A,B,C)上的索引可以用于(A),(A,B)和(A,B,C)上的查询,但它不能用于(B)上的查询)或(B,C)。

如果列都是单独索引的,MySQL(5.0或更高版本)也可以使用Index Merge Optimization

答案 1 :(得分:3)

一般来说,索引会增加查询速度,但减少插入/更新速度,并增加磁盘空间/开销。因此,询问是否应该为每个列组合编制索引就像询问是否应该优化代码中的每个函数一样。它可能会使某些事情变得更快,或者它可能几乎没有帮助,并且它可能只会伤害到它的帮助。

指数的有效性取决于:

  • SELECTs与INSERT和UPDATE的百分比
  • SELECT查询的细节,以及它们是否使用JOIN
  • 正在编制索引的表的大小
  • RAM和处理器速度
  • 使用多少RAM的MySQL设置等

所以,很难给出一般答案。基本的声音建议是:如果查询太慢,则添加索引。并且记得使用EXPLAIN来查看要添加的索引。请注意,这有点像一般建议的数据库版本:在花时间优化之前对您的应用进行配置。

答案 2 :(得分:2)

我的经验是使用SQL Server而不是mysql,这可能会产生影响。但是,通常,引擎可以在单个查询上使用多个索引。虽然拥有更全面的单一索引肯定有好处(它提供了更大的提升,特别是如果它形成覆盖索引),您仍然可以从查询的每个字段使用索引中获益。

此外,请记住,每个索引必须单独维护,因此随着索引数量的增加,写入操作会降低性能。

答案 3 :(得分:2)

仔细创建索引! 我建议收集查询统计信息并确定在搜索时更常使用哪一列,这样您就可以在此特定列上创建聚簇索引(无论如何,当您在多列上创建索引时 - 物理数据只能由单个列排序)< / p>

另请注意,群集索引可能会显着降低UPDATE/INSERT/DELETE查询的性能,因为它会导致物理数据重新排序。

答案 4 :(得分:1)

我发现最好是索引用户搜索的任何内容。实际上,如果要执行对这些列的搜索,我可以通过创建具有多列的索引来获得更好的性能。

例如,如果某人可以同时搜索roleid和groupid,那么拥有这两列的索引实际上会比每个列只有一个索引快一点。但是,在每个可查询列上都有一个索引仍然可以,因为您可能会错过列的组合。

关键考虑因素是查看索引将占用多少空间。由于这些列是整数字段,因此它不应该是一个大问题。创建索引的一点时间可以获得显着的好处。

最好的办法是进行实验。对多个列进行搜索并对其进行计时,然后添加组合索引并重新运行。

答案 5 :(得分:0)

使用名为“SQL sentry plan explorer”的免费工具删除所有索引并对表运行CRUD语句。

它将显示哪些索引是必要的。

索引是基于CRUD创建的,而不是单独创建的。