jim*_*imw 5 index null hints sql-server-2008-r2
我有一个按以下方式定义的表:
CREATE TABLE [dbo].[MyTable]
(
[MyTable_ID] [int] IDENTITY(1,1) NOT NULL,
[COLUMN_WITH_DATA] [varchar](128) NOT NULL,
[COLUMN_A] [varchar](128) NULL,
[COLUMN_B] [varchar](128) NULL,
[COLUMN_C] [bit] NOT NULL
)
Run Code Online (Sandbox Code Playgroud)
和这样创建的索引:
CREATE INDEX [MyTable_Index_ABC] ON [dbo].[MyTable]
(
[COLUMN_A],
[COLUMN_B],
[COLUMN_C]
)
ON [PRIMARY]
Run Code Online (Sandbox Code Playgroud)
我运行以下查询:
SELECT TOP 1 [MyTable].*
FROM [MyTable](UPDLOCK)
WHERE
[MyTable].[COLUMN_A] IS NULL
AND [MyTable].[COLUMN_B] IS NULL
AND [MyTable].[COLUMN_C] = 0
Run Code Online (Sandbox Code Playgroud)
这背后的目标是获取第一个尚未使用的记录的 COLUMN_WITH_DATA 值,然后使用非空值更新其 COLUMN_A 和 COLUMN_B,以将其标记为已使用。
我在 MyTable 中有几百万条记录,其中大约一半都有:COULMN_A 和 COLIMN_B 不是 NULL(表明数据已经被消耗)。
在这种情况下,查询运行非常缓慢,执行计划显示索引:
MyTable_Index_ABC
Run Code Online (Sandbox Code Playgroud)
除非我使用查询提示,否则不使用,在这种情况下查询运行得更快。另一方面,如果我更新所有尚未消耗的行,那就是:
COLUMN_A IS NULL AND COLUMN_B IS NULL
Run Code Online (Sandbox Code Playgroud)
以便 COLUMN_A 和 COLUMN_B 包含空字符串:'' 而不是 NULL,使用索引并且查询再次运行得更快。
两个问题是:
谢谢,
我喜欢直接回答问题;然而,这个话题可以更深入更长时间,因此我在底部添加了几篇文章,扩展了这些细节,供所有人学习。
总之 ...
一些可能影响使用索引的事情(请注意,还有很多原因,您将在下面发布的文章中看到)。引擎的主要优先级是预测如何以最有效/最高效的方式(使用统计数据)尽快从磁盘中获取数据。引擎的主要选择是执行表扫描或索引查找/扫描。(本次对话可以有更深入的内容,但我会将其保留在您问题的上下文中)。
详细 ...
使用表扫描或索引扫描/查找的原因是什么。这些也是在大多数一般情况下确定索引创建和使用的一般帮助程序。遵循以下几个步骤,您将从一开始就获得巨大的收益。
其中一个原因,因为它是在上述意见中提到,是从哪儿使用SELECT *的。SELECT * 是引擎决定避免使用索引的可靠方式。通过从表本身扫描/检索,绕过任何索引,从表(聚集索引/堆)中获取所有字段会更快。第一个人工选择是将您的选择字段最小化为 INDEX KEY 和 INDEX INCLUDES 中的字段。
在第二个原因是多少条记录在表中。记录越少,引擎就越容易简单地扫描表。统计数据可以参与其中。因为引擎会使用统计信息来预测数据在页面/磁盘上的位置,所以可以说没有足够的行/分布来使用索引。
而第三,具有较小的选择性(较少独特)在表中的值,如男性和女性,就越有可能的指数将被使用。在查询中更多使用索引的表将用于高度选择性(更独特)的字段,例如地址表中的邮政编码(只要您的地址列表不是所有具有相同邮政编码的邻居)。
有许多技术和策略。但有一条建议,在阅读和体验索引/统计数据以及如何/将它们放在磁盘/LUNS 上的位置方面变得知识渊博,您将成为一名 DBA 并提供巨大的性能提升。