通过在执行计划中删除排序运算符来优化SQL查询

栏目: 数据库 · 发布时间: 5年前

内容简介:代码日志版权声明:翻译自:http://stackoverflow.com/questions/6001197/optimizing-sql-queries-by-removing-sort-operator-in-execution-plan

我刚刚开始研究通过索引优化我的查询,因为 SQL 数据越来越大而且快速.我查看了优化器如何通过SSMS中的执行计划处理我的查询,并注意到正在使用Sort运算符.我听说 排序 运算符表示查询中的错误设计,因为可以通过索引过早排序.所以这里是一个示例表和数据类似于我在做什么:

IF OBJECT_ID('dbo.Store') IS NOT NULL DROP TABLE dbo.[Store]
GO

CREATE TABLE dbo.[Store]
(
    [StoreId] int NOT NULL IDENTITY (1, 1),
    [ParentStoreId] int NULL,
    [Type] int NULL,
    [Phone] char(10) NULL,
    PRIMARY KEY ([StoreId])
)

INSERT INTO dbo.[Store] ([ParentStoreId], [Type], [Phone]) VALUES (10, 0, '2223334444')
INSERT INTO dbo.[Store] ([ParentStoreId], [Type], [Phone]) VALUES (10, 0, '3334445555')
INSERT INTO dbo.[Store] ([ParentStoreId], [Type], [Phone]) VALUES (10, 1, '0001112222')
INSERT INTO dbo.[Store] ([ParentStoreId], [Type], [Phone]) VALUES (10, 1, '1112223333')
GO

这是一个示例查询:

SELECT [Phone]
FROM [dbo].[Store]
WHERE [ParentStoreId] = 10
AND ([Type] = 0 OR [Type] = 1)
ORDER BY [Phone]

我创建一个非聚簇索引以帮助加快查询速度:

CREATE NONCLUSTERED INDEX IX_Store ON dbo.[Store]([ParentStoreId], [Type], [Phone])

要构建IX_Store索引,我从简单的谓词开始

[ParentStoreId] = 10
AND ([Type] = 0 OR [Type] = 1)

然后我添加ORDER BY的[Phone]列并覆盖SELECT输出

因此,即使构建索引,优化器仍然使用Sort运算符(而不是索引排序),因为[Phone]在[ParentStoreId] AND [Type]之后排序.如果我从索引中删除[Type]列,并运行查询:

SELECT [Phone]
FROM [dbo].[Store]
WHERE [ParentStoreId] = 10
--AND ([Type] = 0 OR [Type] = 1)
ORDER BY [Phone]

那么当然,优化器不使用Sort运算符,因为[Phone]按[ParentStoreId]排序.

所以问题是如何创建一个覆盖查询的索引(包括[Type]谓词),而没有优化器使用Sort?

编辑:

我正在使用的表有超过2000万行

首先,您应该验证排序实际上是一个性能瓶颈.排序的持续时间将取决于要排序的元素的数量,并且特定父存储的存储数量可能很小. (这是假定在应用where子句后应用了sort运算符).

I’ve heard that a Sort operator indicates a bad design in the query since the sort can be made prematurely through an index

这是一个过度泛化.通常,排序运算符可以平均移动到索引中,并且如果仅获取结果集的前几行,则可以显着降低查询成本,因为数据库不再需要获取所有匹配的行(并对它们进行排序所有)找到第一个,但可以读取结果集顺序的记录,并停止一次足够的记录被找到.

在你的情况下,你似乎正在获取整个结果集,所以排序不太可能使事情变得更糟(除非结果集是巨大的).另外,在你的情况下,构建一个有用的排序索引可能不是微不足道的,因为where子句包含一个或.

现在,如果你还想摆脱那个排序运算符,你可以尝试:

SELECT [Phone]
FROM [dbo].[Store]
WHERE [ParentStoreId] = 10
AND [Type] in (0, 1)
ORDER BY [Phone]

或者,您可以尝试以下索引:

CREATE NONCLUSTERED INDEX IX_Store ON dbo.[Store]([ParentStoreId], [Phone], [Type])

尝试让查询优化器仅在ParentStoreId上进行索引范围扫描,然后扫描索引中的所有匹配行,如果类型匹配则输出它们.但是,这可能会导致更多的磁盘I / O,因此减慢了查询速度,而不是加快速度.

编辑:作为最后的手段,您可以使用

SELECT [Phone]
FROM [dbo].[Store]
WHERE [ParentStoreId] = 10
AND [Type] = 0
ORDER BY [Phone]

UNION ALL

SELECT [Phone]
FROM [dbo].[Store]
WHERE [ParentStoreId] = 10
AND [Type] = 1
ORDER BY [Phone]

CREATE NONCLUSTERED INDEX IX_Store ON dbo.[Store]([ParentStoreId], [Type], [Phone])

并对应用服务器上的两个列表进行排序,您可以在其中合并(如合并排序)预分类列表,从而避免完整排序.但是,这真的是一个微型优化,尽管加速排序本身一个数量级,但不太可能影响查询的总执行时间,因为我预计瓶颈是网络和磁盘I / O,特别是考虑到由于索引未聚集,磁盘将执行大量的随机访问.

代码日志版权声明:

翻译自:http://stackoverflow.com/questions/6001197/optimizing-sql-queries-by-removing-sort-operator-in-execution-plan


以上所述就是小编给大家介绍的《通过在执行计划中删除排序运算符来优化SQL查询》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

数字战争

数字战争

[英]查尔斯·亚瑟 / 余淼 / 中信出版社 / 2013-6-1 / 49

1998年,数码世界初具雏形。 至此以往,大浪淘沙。随着IT产业的迅猛发展,涌现出了以苹果、谷歌、微软为首的行业巨头。它们为争夺数码世界不同分支的霸主地位而争斗,包括搜索技术、移动音乐、智能手机和平板电脑市场。它们可利用的武器包括硬件、软件以及广告。同时,它们要赌上的则是公司的声望,当然,还有我们的未来。然而,无论在产品创新还是在战略优势上,这些企业彼此竞争、彼此砥砺,推动了行业的良性发展。......一起来看看 《数字战争》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具