Ros*_*ana 7 sql-server optimization index-tuning
为什么NOT IN
执行INDEX SCAN
而不是INDEX SEEK
?
这是我目前在桌子上的索引,
CREATE NONCLUSTERED INDEX [idx_dmcasarms_CourseList_cDesc]
ON [dbo].[courselist]
(
[c_desc] ASC,
[c_code] ASC
)
Run Code Online (Sandbox Code Playgroud)
SQL语句,
SELECT c_code CourseCode
FROM courselist
WHERE c_desc = 'BACHELOR OF SCIENCE IN INFORMATION TECHNOLOGY'
GO
SELECT c_code CourseCode
FROM courselist
WHERE c_desc NOT IN ('PRE SCHOOL', 'BASIC EDUCATION', 'SCIENCE HIGH SCHOOL')
GO
Run Code Online (Sandbox Code Playgroud)
和执行计划,
无论如何我可以优化这个吗?
小智 7
它执行扫描,因为它必须找到不在列出的值中的所有值。想象一下,在电话簿中查找所有不是“Smith”的姓氏值。然后你必须扫描整本书。如果您只需要找到姓氏值为“Smith”的人,那么您可以只查找该部分。
至于如何优化,不幸的是,如果扫描成本太高而无法接受,则需要重新设计逻辑以避免 NOT IN。因此,如果您能以某种方式将 NOT IN 更改为 IN 或 =,那么对数据库引擎来说会更好。当然,这有时是不可能的,然后您必须权衡查询成本与重新设计逻辑的成本。
您也可以将查询编写为
SELECT c_code CourseCode
FROM courselist
WHERE c_desc < 'BASIC EDUCATION'
UNION ALL
SELECT c_code CourseCode
FROM courselist
WHERE c_desc > 'BASIC EDUCATION' AND c_desc < 'PRE SCHOOL'
UNION ALL
SELECT c_code CourseCode
FROM courselist
WHERE c_desc > 'PRE SCHOOL' AND c_desc < 'SCIENCE HIGH SCHOOL'
UNION ALL
SELECT c_code CourseCode
FROM courselist
WHERE c_desc > 'SCIENCE HIGH SCHOOL'
Run Code Online (Sandbox Code Playgroud)
获得四个范围搜索。
除非任何NOT IN
值非常常见,否则我希望这会更糟而不是更好。
如果这些值是通用的,那么上次我看这个时,SQL Server 最好的做法是跳过第一个索引值并扫描其余的值。
一个完全操纵的例子,看看这可能更好的情况......
CREATE TABLE [dbo].[courselist](
[c_desc] VARCHAR(20),
[c_code] CHAR(880))
CREATE NONCLUSTERED INDEX [idx_dmcasarms_CourseList_cDesc]
ON [dbo].[courselist]([c_desc] ASC,[c_code] ASC);
WITH T AS (SELECT TOP (10000) v1.number FROM master..spt_values v1, master..spt_values v2)
INSERT INTO [dbo].[courselist]
SELECT X, number
FROM T
CROSS JOIN (VALUES ('PRE SCHOOL'),
('SCIENCE HIGH SCHOOL')) V(X)
UNION ALL
SELECT REPLICATE('A',20), 1
Run Code Online (Sandbox Code Playgroud)
在我的带有热缓存的机器上,它进行了NOT IN
一次完整扫描和 3,132 次逻辑读取,时间为 20 毫秒。而多次搜索显示 28 次读取和 0 毫秒的经过时间。
归档时间: |
|
查看次数: |
1721 次 |
最近记录: |