使用动态SQL过滤子句的效率

时间:2017-11-14 21:15:41

标签: sql sql-server dynamic-sql

我正在尝试编写一个相对通用的动态查询生成器,并对某些技术感到好奇。我有一个列表页面,其中包含20到100个过滤器。每个过滤器都是“标准”,因为SqlGenerator类知道如何创建SQL或“自定义”,以便过滤器为SqlGenerator提供需要INCLUDEd和WHERE子句的策略。

1。)执行过滤条款的最佳方法是什么?

a)非常简单,只要保持每个过滤器分开并包含:

and exists (select 'x' from [company] c
            where c.CompanyId = p.CompayId
            and c.Rating >= 4)
and exists (select 'x' from [company] c
            where c.CompanyId = p.CompayId
           and c.CityId = 5)

b)合并为单个存在但不需要构建/管理INCLUDE。

and exists (
    select 'x'
    from [company] c
    where c.CompanyId = p.CompayId
    and c.Rating >= 4 and c.CityId = 5)

c)很难动态构建但是对我来说最干净,看起来它会最有效地执行。

select x, y, z
from product p
join company c on p.CompanyId = p.ProductId
where c.Rating >= 4 and c.CityId = 5

d)我偶尔也会看到,在联接中放置where子句的某些部分会使查询更有效。这样做是否有意义:

select x, y, z
from product p
join company c on p.CompanyId = p.ProductId and c.Rating >= 4 and c.CityId = 5

2。)由于这是动态的,我担心我会失去查询缓存计划和索引的所有好处。总是包含某些连接和子句是否有意义,希望它们能够被优化掉以便使用相同的计划/索引?

select x, y, z
from product p
join company c on p.CompanyId = p.ProductId
where c.Rating >= ISNULL(@Rating, c.Rating)
and c.CityId = ISNULL(@CityId, c.CityId)

3。)最后,子句和连接的顺序是否会影响查询计划缓存?也就是说,如果我切换AND语句的顺序,那两个不同的计划是什么?

1 个答案:

答案 0 :(得分:2)

您的查询会执行不同的操作。您应该选择在语义上执行所需的版本。

(1a)和(1b),做不同的事情。在某些情况下,他们会做同样的事情 - 特别是如果companyid在表格中是唯一的。我不知道这个表或其他表是否属实。

(1a)/(1b)和(1c)做不同的事情,特别是如果companyId可以复制的话。

(1c)/(1d) - 对于内部联接,我从未看到将条件从where移动到on子句的区别。当然,这可以对外部联接产生影响。

(2)我会更关心使用索引而不是查询缓存。在大多数情况下,仅仅阅读一些额外的数据页面需要比重新编译更长的时间。

(3)对于长期复杂的查询,条件和表格的排序很重要,但这通常不是主要问题。