我正在尝试编写一个相对通用的动态查询生成器,并对某些技术感到好奇。我有一个列表页面,其中包含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语句的顺序,那两个不同的计划是什么?
答案 0 :(得分:2)
您的查询会执行不同的操作。您应该选择在语义上执行所需的版本。
(1a)和(1b),做不同的事情。在某些情况下,他们会做同样的事情 - 特别是如果companyid
在表格中是唯一的。我不知道这个表或其他表是否属实。
(1a)/(1b)和(1c)做不同的事情,特别是如果companyId
可以复制的话。
(1c)/(1d) - 对于内部联接,我从未看到将条件从where
移动到on
子句的区别。当然,这可以对外部联接产生影响。
(2)我会更关心使用索引而不是查询缓存。在大多数情况下,仅仅阅读一些额外的数据页面需要比重新编译更长的时间。
(3)对于长期复杂的查询,条件和表格的排序很重要,但这通常不是主要问题。