我在ASP.NET应用程序中有一段代码,它从参数列表构建SQL查询。参数的数量可以变化,因此可以向此查询添加各种标准。该数据库是Microsoft SQL Server 2008。
所有AND和OR都是以编程方式生成的。
查询执行时间超过3秒,但经过一些分析和索引后,运行时间不到一秒。我仍然认为查询本身可以进行优化。我看过执行计划,但这对我来说并不重要 - 不是SQL大师。
我想知道查询是否可以以更智能的方式完成 - 我无法弄明白。以下是查询示例:
SELECT [id], [WorkTitle], [CreateDate], [UpdateDate], [Writer], [ValidFrom],
[ValidTo], [Text]
FROM dbo.Texts T
WHERE Category_id = 3 AND '2012-11-06' BETWEEN ValidFrom AND ValidTo
AND (EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 1 AND CL.Value = '95068')
OR NOT EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 1))
AND (EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 2 AND CL.Value = 'C')
OR NOT EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 2))
AND (EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 3 AND CL.Value = 'HEL')
OR NOT EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 3))
AND (EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 4 AND CL.Value = 'CC')
OR NOT EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 4))
AND (EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 5 AND CL.Value = NULL)
OR NOT EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 5))
AND (EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 7 AND CL.Value = '321')
OR NOT EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 7))
AND (EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 9 AND CL.Value = 'DK7778')
OR NOT EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 9))
AND (EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 10 AND CL.Value = 'TFS')
OR NOT EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 10))
AND (EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 11 AND CL.Value = 'TMP')
OR NOT EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 11))
AND (EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 13 AND CL.Value = 'OY-VKB')
OR NOT EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 13))
感谢任何提示和技巧。
干杯 延
答案 0 :(得分:2)
对于表格Texts
我会在(Category_id, ValidFrom) INCLUDE (ValidTo)
上添加一个索引(如果没有)。 (如果您已经在(Category_id, ValidFrom, ValidTo)
或(Category_id, ValidFrom)
上设置了索引,那么它们也可能非常好。
对于Criteria_List
表,(Text_id, Criteria_id, Value)
上的索引可能足以让优化器生成一个好的执行计划。
第二个选项(或者更好的是,您必须使用表大小和分布测试执行计划和运行时间)将是两个索引,一个在(Criteria_id, Text_id)
上,一个在{{1}上}。
你可以重写这样的10个条件 - 但是无论如何都应该注意索引:
(Criteria_id, Value, Text_id)
答案 1 :(得分:0)
我建议的一件事是更改数据库设计,以便您可以识别CriteriaList.value记录,而不是按原样列出它们。这将使您的查询更加灵活,意味着您应该能够摆脱存在/不存在的所有或大部分内容,并且可能会加快您的查询速度。