sql – 我可以使用索引优化包含WHERE值<> 2的请求

这是我的要求:

SELECT TOP 10 * FROM BigTable WHERE值<> 2;

BigTable有点特别,因为Value列包含每行的相同值:2.在实际情况中,可能有一些行具有不同的值,但不是很多.我确实需要找到这些流氓行.但是,我不知道在设计时哪个值(2只是一个例子)(但我知道在查询时).

请求很慢(大约5分钟); BigTable包含1000万行.

所以我在Value列上添加了一个索引,它的类型为smallint. 10分钟后,索引建成了,我再次运行了请求.它仍然很慢.

这个问题可以在这里复制:http://sqlfiddle.com/#!6/6ce0f/1

此时,我的猜测是SQL Server无法使用带有<>的查询的索引运算符,但我不确定为什么?例如,此另一个查询只需2秒:SELECT TOP 10 Value FROM BigTable GROUP BY Value(并返回单行,其值为2).

我正在考虑拆分成多个查询:一个用于获取不同值的列表,另一个用于获取所有流氓行,例如SELECT TOP 10 * FROM BigTable WHERE Value = x等(所有值都不是2) ,但有更好的解决方案吗?

编辑:

此查询的想法是查找在更新大多数行的进程之后尚未更新的行.基本上,我正在与另一个数据源同步.每次运行此过程时,我都会增加该值,并使用新值(以及更新的数据)更新每一行.在该过程结束时,我可以检查哪些行具有旧值,并删除它们.这个过程有点长,这就是为什么我不想先截断表并插入后,因为我需要先前的数据在这个流程执行期间保持可用.

索引是使用此请求创建的(由Entity Framework Core生成,但我手动进行查询测试):

CREATE NONCLUSTERED INDEX [IX_Value] ON [dbo].[BigTable]
(
    [Value] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)

编辑2:

以下是来自SSMS的估计查询计划(没有什么是绝密的,但由于我没有问我是否可以透露项目的内容,我已经模糊了数据库名称;在这些屏幕截图中,表格和列名称都是真实的那些)

Value<>的查询计划2
《sql – 我可以使用索引优化包含WHERE值<> 2的请求》” /></a></p><p>您可以看到它根本不使用IX_Establishments_UpdateTag(索引扫描在主键上).执行时间:5分18秒(在这次运行中,我有一行,其值/ UpdateTag不是2)</p><p>Value <a href=《sql – 我可以使用索引优化包含WHERE值<> 2的请求》” /></a></p><p>这里使用了IX_Establishments_UpdateTag索引.执行时间小于1秒(SSMS报告0秒).</p><p> 最佳答案   SQL可以使用<>的索引查询. “可以”并不意味着它会,它只意味着优化器会考虑它们.</p><p>当OR存在时,SQL通常会出现问题 – 这些通常(可能总是?)导致全表扫描.值IN(1,2,3)必须“翻译”为“值= 1或值= 2或值= 3”.</p><p>价值< 2 OR值> 2对你我来说看起来很明显,但优化器可能不够聪明,不能意识到这相当于Value<> 2 …所以它将它作为一个OR,并随着表扫描突然显示.</p><p>至于为什么Value<> 2不能快速运行,它取决于您的数据.做一些猜测,而不是在这里进行必要的细节:</p><p>>你有很多数据(1000万行,没问题,但是每行有多少字节?…导致讨论Pages和Extents.)<br />>你说很少有<> 2(或任何你的目标值)<br />>查询优化器使用索引统计信息来确定是否使用给定索引<br />>通过对数据进行采样来构建统计数据.如果数据很少,那么在构建统计信息时可能没有采样非2值,因此优化器认为所有值都是2并且将索引标记为很大程度上无用.</p><p>(可以通过运行查看统计信息</p></p><pre><code>dbcc show_statistics (<TableName>, <IndexName>)
</code></pre><p>但是,了解统计数据完全是另一回事.如果你想走到这一步,请在网上查看相关文章和讨论.)</p><p>以上是很多“为什么”.如果没有深入研究数据,分析统计数据,并且这样做,我就没有现成的解决办法.作为一个虽然实验,如果我们转动你的</p><pre><code>where not (Value >= 2 and Value <= 2)
</code></pre><p>看起来很傻,可能不起作用,但值得一试,看看会发生什么.</p></div><footer class=

点赞