我有一个包含 1.5 亿条记录和 8 个索引的表。其中一个索引是 on userId
。我过滤了很多当前的查询userId
,因此这个索引工作得很好。对于其中一个查询,我必须扩展 where 子句以包含regionId
和productId
列。我有两个选择:我可以使用这些新列创建一个新索引(userId, regionId, productId)
或将这些新列添加到现有索引中。哪个是更好的选择?如果我修改现有索引,它会影响其他已经使用的查询吗userId
?
我的目标:
我希望我当前的查询扩展 where 子句以包含RegionId
并productId
运行得更快,但我不希望我的其他查询只userId
在 where 子句中受到影响。如果我在上面添加一个新索引,(userid, regional, productid)
我可以做到这一点,但我不确定我是否在复制该索引,因为我已经有一个现有索引,userId
我可以在该索引上扩展以包含regionid
和productId
. 但我不确定修改现有索引的后果。
谢谢你的时间!
假设您的查询过滤
RegionId
并过滤同一组谓词,那么是的,您可以通过将非聚集索引定义ProductId
为.UserId
(UserId, RegionId, ProductId)
但是,对数据库的任何索引更改都会影响现有查询。即使您已经有了一个关于
(UserId)
您的查询当前正在使用的索引,也不能保证它们不会切换到使用该索引(UserId, RegionId, ProductId)
,即使是作为一个单独的新索引。是的,您很可能会创建没有实际好处的冗余。当存在冗余索引的情况(例如您所提议的)时,这是相当极端的情况。此外,在对表进行
INSERT
ed、UPDATE
ed 或DELETE
dd 时,您会产生更多开销,因为需要为这些 DML 更改维护更多索引。通常最好扩展现有索引的定义。找出答案的唯一方法是通过测试。您可以保存原始索引定义,并在遇到问题时将其恢复原样。您还可以通过在 SSMS 中右键单击它们并单击或通过 T-SQL 来禁用索引
Disable
,例如:ALTER INDEX IndexName ON SchemaName.TableName DISABLE;
.创建尽可能少的索引以覆盖尽可能多的查询通常是一个很好的策略。而且,需要冗余索引的情况很少见,因此您可能会通过删除旧索引并用定义
(UserId)
更好的索引替换它来做得很好(UserId, RegionId, ProductId)
。但是,当然,在不知道所有涉及的查询的确切谓词的情况下,其中很多都是猜测。当在这里询问性能问题时,您通常应该向您的帖子添加一些相关查询,以及完整的表和现有索引定义。
例如,如果您尝试改进的查询使用不等式搜索,那么
UserId
您建议的索引可能无论如何对这些查询都没有帮助,并且单独的索引(RegionId, ProductId)
(同时单独保留原始索引UserId
)可能是最好的回答。这实际上取决于您查询的具体情况。