我有一个基本表格如下。
create table Orders
(
ID INT IDENTITY(1,1) PRIMARY KEY,
Company VARCHAR(3),
ItemID INT,
BoxID INT,
OrderNum VARCHAR(5),
Status VARCHAR(5),
--about 10 more columns, varchars and ints and dates
)
我正在尝试优化我的所有SQL,因为我遇到了一些死锁和一些缓慢的问题 - 但我不是这方面的专家!
我创建了一些索引:
在ID(主键)上聚集。
([ItemID])上的非聚集索引
([BoxID])上的非聚集索引
([公司],[订单号],[状态])上的非聚集索引
在其他一些专栏上可能还有1或2个
但我对结果并不满意。
SELECT * FROM Orders WHERE ItemID=100
给我一个索引搜索+一个键查找和一个嵌套循环(内连接)。 我明白为什么 - 但不知道我是否应该采取任何措施。他们的密钥查找是批次的97%,看起来很糟糕!
使用的每个查询都会拉回表中的每一列,但我不喜欢在索引中包含每一列的想法。
我现在正在进行更改,以查询[公司]字段中的所有内容。 每个查询都将使用它,因为从不的结果应包含多于1个值。所以他们都会改变:
SELECT * FROM Orders WHERE ItemID=100 --Old
SELECT * FROM Orders WHERE Company='a' and ItemID=100 --New
但是执行计划给了我完全相同的不包括公司(这让我感到惊讶!)。
为什么两个执行计划高于同一个? (目前我[公司]没有索引)
是否值得将[公司]添加到我的所有索引中,因为它似乎可以 0与执行计划不同?
我应该只为[公司]添加1个单一索引并保留原始索引吗? - 但那会 意味着每个查询都有2个搜索?
是否值得“包括”索引中的所有其他列以避免使用 密钥查找? (使得该指数更大,但可能 加快速度?),即
CREATE NONCLUSTERED INDEX [IX_Orders_MyIndex] ON [Orders]
( [Company] ASC, [OrderNum] ASC, [Status] ASC )
INCLUDE ([ID],[ItemID],[BoxID],
[Column5],[Column6],[Column7],[Column8],[Column9],[Column10],etc)
如果我在4或5个索引上做到这一点,那似乎很麻烦。
基本上我有4-5个经常运行的查询(有些选择和更新),所以我想让它尽可能高效。 所有查询都将使用[company]字段,至少还有1个。我应该怎么做呢。
任何帮助表示赞赏:)
答案 0 :(得分:3)
在执行计划中,您说查找占批次的97%。
在这种情况下,它并不意味着什么,因为索引搜索速度非常快,而且您没有那么多操作要做。
该查找实际上是您根据指定的索引读取的记录。
为什么两个执行计划高于同一个? (目前我[公司]没有索引)
Non-Clustered index on ([Company],[OrderNum],[Status])
仅当您的where子句中出现Company
,OrderNum
和Status
时,才会考虑此索引。
当仅传递company
时,连续索引会生成一个看起来像0000000000000的密钥,它会创建一个不完整的密钥,需要使用通配符将另一个密钥用于值。
看起来有点像这样:key like 'XXX%'
这个逻辑需要一个耗时的索引扫描。
优化程序将确定首先从ItemID
索引中搜索和排序,然后扫描这些索引以匹配所需公司的任何内容。
是否值得将[公司]添加到我的所有索引中,因为它似乎与执行计划有所不同?
您应该考虑使用Company
索引,而不是将其添加到所有索引中。
复合索引可以通过减少嵌套循环的数量来加快速度,但是你必须彻底思考。
您添加到此类索引的字段的顺序非常重要,它们应按唯一性排序,以便更好地进行搜索。此外,您永远不应添加可能未在查询中使用的字段。
我应该只为[公司]添加1个单一索引并保留原始索引吗? - 但这是否意味着每个查询都有2次搜索?
有多个索引搜索并不是那么糟糕,它们通常是并行的,只有两者的结果匹配在一起。
是否值得“包括”索引中的所有其他列以避免密钥查找? (使指数变得更大,但可能加速它?)
值得一提的是,只有少数几个字段在where子句中是可选的,或者当您使用指定索引时只有那些字段时才会选择这些字段。
最后的注释
所有索引都不相等,比较字符串(varchar)与比较数字(整数,日期时间,字节等)不同。
另外,保持它们清洁有很大帮助,如果你的索引碎片化,它们在性能提升方面将毫无用处。