组合多列索引以及多个单列索引

时间:2014-01-25 11:46:25

标签: sql-server indexing

我想知道在以下情况下同时定义两种索引类型有什么害处。

Tasks

  TaskID (Primary, Auto Number)
  OwnerID (Single Column Index)
  AssignedToID (Single Column Index)
  DateUpdated (Single Column Index)
  TaskStatus (Single Column Index)

  Mutli Column Index (AssignedToID, DateUpdated)

以下主要查询... DateUpdated的查询是可选的。

  • 管理员可以按日期过滤任务
  • 访问单列索引DateUpdated

    WHERE 
        DateUpdated <= startDate 
        AND DateUpdated <= endDate
    ORDER BY
        DateUpdated DESC
    
  • 访问单列索引DateUpdated

    WHERE
         TaskStatus = 'Active' 
    ORDER BY
         DateUpdated DESC
    
  • 用户可以过滤仅分配给他们的任务

  • 访问多列索引

    WHERE 
        DateUpdated <= startDate 
        AND DateUpdated <= endDate
        AND AssignedToID = userID
    ORDER BY
        DateUpdated DESC
    
  • 访问多列索引

    WHERE 
         AssignedToID = userID
         AND TaskStatus = 'Active'
    ORDER BY
         DateUpdated DESC
    
  • DateUpdated未在任何条件中引用

  • 访问单列索引TaskID

    WHERE 
        AssignedToID = userID
        AND TaskStatus = 'Active'
    ORDER BY
        TaskID DESC
    

看起来我可以通过在某些常见查询中定义多列索引来提高性能,我有以下问题。

  1. 定义合并索引以及多个索引是否有任何损害?
  2. 如果查询包含每列的谓词而不管查询中列的顺序如何,SQL是否会优先考虑单索引合并的组合索引?
  3. 如果您有两个索引可能有害的示例,我想了解原因和方法,以便我可以相应地设计我的索引。
  4. 我的数据库操作是95%读取和5%写入,所以我不太担心索引写入性能问题,但我的读取性能最重要。

1 个答案:

答案 0 :(得分:1)

  

定义组合索引和多个索引是否有任何危害?

我宁愿称之为维护费用而不是伤害:
- 对于每个新索引,此表上的INSERT / UPDATE / DELETE都会慢一点 - 索引占用一些磁盘空间。

  

如果查询包含每列的谓词,而不管查询中列的顺序如何,SQL是否会优先考虑单索引合并的组合索引?

查询中的列顺序无关紧要。

索引中的列顺序很重要 所以:
AssignedToIDDateUpdated)上的索引可以用于搜索而不是(AssignedToID)上的索引,但是 (DateUpdatedAssignedToID)上的索引不能用于搜索,而不能用于(AssignedToID)上的索引。

查询优化器将根据估计的成本选择要使用的索引,它根据统计信息计算(表/索引中的行数以及值的分布方式)。
它可能决定根本不使用你的索引 - 如果行数很小并且扫描整个表的成本更低,或者索引的选择性不够。

如果查询包含AssignedToIDDateUpdated上的谓词 - 查询优化器更有可能使用索引(AssignedToIDDateUpdated)而不是索引( AssignedToID)。
但是,它取决于查询的所有其他元素以及数据库中的实际数据。

  

如果您有两个索引可能有害的示例,我想了解原因和方法,以便我可以相应地设计索引。

当数据库或/和请求数量显着增加时,开销可能会变得明显。

More about "too many indexes"
General indexing guidelines


根据您的主要查询,非聚集索引应该是:

  • DateUpdated
  • AssignedToIDDateUpdated

也许:

  • TaskStatus) - 但是如果假设90%的任务都是'Active'而您只查询'Active' - 那么它就没用了。

不需要:

  • AssignedToID) - 因为(AssignedToIDDateUpdated)索引就足够了。

之后,您可以验证测试数据库的假设,数据足够接近生产。