我有以下查询:
SELECT TOP (100000)
[Filter1].[ID] AS [ID],
[Filter1].[FIELD1] AS [FIELD1],
[Filter1].[FIELD2] AS [FIELD2],
[Filter1].[FIELD3] AS [FIELD3],
[Filter1].[FIELD4] AS [FIELD4],
...
[Filter1].[FIELD30] AS [FIELD30],
FROM ( SELECT [Extent1].[ID] AS [ID],
[Extent1].[FIELD1] AS [FIELD1],
[Extent1].[FIELD2] AS [FIELD2],
[Extent1].[FIELD3] AS [FIELD3]
...
[Filter1].[FIELD30] AS [FIELD30],
row_number() OVER (ORDER BY [Extent1].[ID] ASC) AS [row_number]
FROM [dbo].[TABLE] AS [Extent1]
WHERE (N'VALUE1' <> [Extent1].[**FIELD2**]
AND (N'VALUE2' <> ([Extent1].[**FIELD3**])
AND ([Extent1].[**FIELD4**] IN (VALUE1, VALUE2, VALUE3, .... VALUE9)))
AS [Filter1]
WHERE [Filter1].[row_number] > 0
ORDER BY [Filter1].[ID] ASC
由于需要选择的行数(几百万),我正在批量执行,因此row_number过滤。目前,查询分析器表示在FIELD1上进行了聚簇索引扫描。我仍然想要更好的性能,这就是为什么我尝试对WHERE和ORDER BY子句中的字段进行索引。
到目前为止我尝试过:
上的非聚集索引
FIELD2 ASC,
FIELD3 ASC,
FIELD4 ASC,
ID ASC
每一种可能的排列。查询执行时间加倍并增加三倍。
为什么会发生这种情况,我可以创建哪种索引来加快速度?
顺便说一句,我正在运行SQL Server 2005,因此无法使用过滤索引。兼容级别为7.0。
答案 0 :(得分:1)
嘿,我在本地进行了一些虚拟数据测试。考虑到你现在没有任何索引,我正在提出这个建议。或者如果你有任何测试,请先放弃这个建议。
1)[FIELD1]未在任何过滤器中使用。将主键设为非聚类。
2)现在在列上创建聚簇索引(FIELD2 ASC,FIELD3 ASC,FIELD4 ASC)
3)您在[ID]列上排序了ROW_NUMBER函数。因此,在外部order by子句中使用[Row_Number]而不是[ID]
4)更改查询中的Where筛选器顺序。首先保持[FIELD4]滤波器,然后使用[FIELD2]和[FIELD3]滤波器。
5)如果列的数据类型[FIELD2]和[FIELD3]是INT / NUMERIC / DATE,那么您可以替换“&lt;&gt;”运算符与“(&gt; OR&lt; =)”的组合。
6)如果列[FIELD2]和[FIELD3]的数据类型为STRING,则将那些WHERE过滤器保留为“&lt;&gt;”操作
在SQL FIDDLE上查看这些建议。这个没有任何数据,但解释了上面的索引和查询建议
根据上述建议,您将获得“Index Seek”,这应该会给您带来良好的性能提升。在我使用2M行表的虚拟数据进行测试时,它在SSMS中在2秒内返回50k行。
答案 1 :(得分:0)
此处的解决方案是忽略where和order by子句的索引,而是将order by子句更改为&#34; ORDER BY [Filter1]。[FIELD2] ASC&#34;已存在聚集索引的位置。这样,在3秒内返回100k行。文件中的排序已更改,但服务器端分页未受影响。