背景:生产环境SQL语句查询过慢(数据总量在350万左右),日志中心一直报警
解决过程:分析无果后,求助于公司的DBA,DBA分析后建议在语句中指定索引
解决:在SQL语句中指定索引,效果相当明显,亲测有效
优化前SQL:
SELECT ROW_NUMBER() OVER ( ORDER BY sc.ModifyTime DESC ) AS RowNumber , sc.CommodityCode AS ChannelCommodityCode , sc.OutShopCommodityCode AS OutItemId , sc.IsShelf , sc.OriginPrice , sc.SalePrice , sc.CreateBy , sc.CreateTime , sc.ModifyTime , sc.StoreCode , sc.ShopCommodityId AS ChannelStoreMappingId , sc.ShopCommodityName AS O2OCommodityName , sc.ShopCommodityTitle AS O2OCommodityTitle , sc.Remark AS Comment , sc.OutShopSPUCode , sc.ModifyBy , sc.ChannelCode FROM dbo.Channel_ShopCommodity AS sc WITH ( NOLOCK ) WHERE sc.Disabled = 0 AND sc.ChannelCode = '9000000009' AND sc.CityId = 'eabbe02f-59e0-46e6-90e7-cd8a89dbb98f';
优化后SQL(指定使用索引IX_CityId):
SELECT ROW_NUMBER() OVER ( ORDER BY sc.ModifyTime DESC ) AS RowNumber , sc.CommodityCode AS ChannelCommodityCode , sc.OutShopCommodityCode AS OutItemId , sc.IsShelf , sc.OriginPrice , sc.SalePrice , sc.CreateBy , sc.CreateTime , sc.ModifyTime , sc.StoreCode , sc.ShopCommodityId AS ChannelStoreMappingId , sc.ShopCommodityName AS O2OCommodityName , sc.ShopCommodityTitle AS O2OCommodityTitle , sc.Remark AS Comment , sc.OutShopSPUCode , sc.ModifyBy , sc.ChannelCode FROM dbo.Channel_ShopCommodity AS sc WITH ( NOLOCK, INDEX= [IX_CityId] ) WHERE sc.Disabled = 0 AND sc.ChannelCode = '9000000009' AND sc.CityId = 'eabbe02f-59e0-46e6-90e7-cd8a89dbb98f';
注意事项:使用指定索引后,必须保证Where条件中有这个筛选条件,否则索引不生效,查询语句耗时仍然会很长
SELECT ROW_NUMBER() OVER ( ORDER BY sc.ModifyTime DESC ) AS RowNumber , sc.CommodityCode AS ChannelCommodityCode , sc.OutShopCommodityCode AS OutItemId , sc.IsShelf , sc.OriginPrice , sc.SalePrice , sc.CreateBy , sc.CreateTime , sc.ModifyTime , sc.StoreCode , sc.ShopCommodityId AS ChannelStoreMappingId , sc.ShopCommodityName AS O2OCommodityName , sc.ShopCommodityTitle AS O2OCommodityTitle , sc.Remark AS Comment , sc.OutShopSPUCode , sc.ModifyBy , sc.ChannelCode FROM dbo.Channel_ShopCommodity AS sc WITH ( NOLOCK, INDEX= [IX_CityId] ) WHERE sc.Disabled = 0 AND sc.ChannelCode = '9000000009' AND sc.StoreCode IN ( '10000723' );
以下截图为上面语句的耗时:
去除指定索引后再次执行
SELECT ROW_NUMBER() OVER ( ORDER BY sc.ModifyTime DESC ) AS RowNumber , sc.CommodityCode AS ChannelCommodityCode , sc.OutShopCommodityCode AS OutItemId , sc.IsShelf , sc.OriginPrice , sc.SalePrice , sc.CreateBy , sc.CreateTime , sc.ModifyTime , sc.StoreCode , sc.ShopCommodityId AS ChannelStoreMappingId , sc.ShopCommodityName AS O2OCommodityName , sc.ShopCommodityTitle AS O2OCommodityTitle , sc.Remark AS Comment , sc.OutShopSPUCode , sc.ModifyBy , sc.ChannelCode FROM dbo.Channel_ShopCommodity AS sc WITH ( NOLOCK ) WHERE sc.Disabled = 0 AND sc.ChannelCode = '9000000009' AND sc.StoreCode IN ( '10000723' );
我们会发现耗时明显减少。
由此总结:如果确保某个条件一定会传并且该字段上加了索引,可以使用指定索引提升性能,但是使用指定索引要慎重,避免因为指定索引的Where条件不传又引起的查询耗时变长