表定义:
CREATE TABLE [his].[38] (
[ID] int IDENTITY(1,1) NOT NULL,
[Time] datetime NOT NULL,
[ItemCode] int NOT NULL,
[AVG] float(53) NOT NULL,
[P1] float(53) NULL,
[P2] float(53) NULL,
[P3] float(53) NULL,
[P4] float(53) NULL,
CONSTRAINT [PK_HIS_38] PRIMARY KEY NONCLUSTERED ([ID])
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
ON [PRIMARY]
)
ON [PRIMARY]
GO
ALTER TABLE [his].[38] SET (LOCK_ESCALATION = TABLE)
GO
CREATE NONCLUSTERED INDEX [IX_card_time]
ON [his].[38] (
[Time] ASC
)
GO
CREATE NONCLUSTERED INDEX [Index_ItemCode_avg_time]
ON [his].[38] (
[ItemCode] ASC,
[AVG] ASC,
[Time] ASC
)
GO
问题:
执行下面的查询:
SELECT
ItemCode,
max([AVG]) [MaxAVG],
max([Time]) [Time]
from Resistance.his.[38] WITH(NOLOCK)
where 1 = 1
and time >= '2022-01-05 00:00:00'
and time <= '2022-01-12 23:59:59'
GROUP BY ItemCode
性能很慢。
解释执行计划中发现:走的是“索引扫描”
。并非命中“索引查找”
即未正确命中Index_ItemCode_avg_time
测试:
- 强制使用
Index_ItemCode_avg_time
SELECT
ItemCode,
max([AVG]) [MaxAVG],
max([Time]) [Time]
from Resistance.his.[38] WITH(INDEX(Index_ItemCode_avg_time), NOLOCK)
where 1 = 1
and time >= '2022-01-05 00:00:00'
and time <= '2022-01-12 23:59:59'
GROUP BY ItemCode
解释执行计划中发现:走的仍旧是“索引扫描”
,说明我们建立的Index_ItemCode_avg_time
有问题。
- 强制使用
IX_card_time
SELECT
ItemCode,
max([AVG]) [MaxAVG],
max([Time]) [Time]
from Resistance.his.[38] WITH(INDEX(IX_card_time), NOLOCK)
where 1 = 1
and time >= '2022-01-05 00:00:00'
and time <= '2022-01-12 23:59:59'
GROUP BY ItemCode
解释执行计划中发现:走的是“RID查找”
。
RID查找
是什么呢?就是说sql先根据time
条件字段“索引查找”
,然后再回去把其他字段查出来(这个过程叫RID查找)。
思考:
从测试上来看,并结合查找相关资料,我们的多字段组合索引的顺序可能出了问题。
下面调整一下索引顺序:
-- 删除原索引
drop index Index_ItemCode_avg_time on [his].[38];
-- 新定义索引
CREATE NONCLUSTERED INDEX [Index_time_ItemCode_avg] ON [his].[38]
(
[Time] ASC,
[ItemCode] ASC,
[AVG] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY];
最后测试:
SELECT
ItemCode,
max([AVG]) [MaxAVG],
max([Time]) [Time]
from Resistance.his.[38] WITH(NOLOCK)
where 1 = 1
and time >= '2022-01-05 00:00:00'
and time <= '2022-01-12 23:59:59'
GROUP BY ItemCode
解释执行计划中发现:走的是“索引查找”
。
解决。
小结:
多字段的组合索引在建立的时候要考虑两个问题:
- 要包含where条件字段、select查询字段(当然不能建立太多、太乱详细请自行研究);
- 顺序要正确!先where条件字段,后select查询字(我上面出现的问题原因就出在这)。
网友评论