2

我正在重写一个旧的遗留系统。它有一个名为checkExisting(). 旧系统使用查询从 MSSQL 数据库中提取对象,如下所示(使用 ADO DB):

SELECT ObjectId, Name..... 
FROM tblRegisteredIncludes   
WHERE UPPER("Name") IN ('PROGA.H', 'PROGB.H'...............  list)

有很多类似的表,tblRegisteredIncludes但是 SQL 是按表名分组的,并且使用带有对象名称列表的 IN 子句。

这执行得很快,因为 SQL Server 在一次扫描中收集了所有对象,并且Name在表中的列上有一个索引。

但是,在新系统中,我不能使用相同的 SQL,因为WHERE条件更复杂。它还使用 Source 字段,有时还使用条件中的其他字段。我有大量的单个 SQL 查询:

SELECT ObjectId, Name..... FROM tblRegisteredIncludes   
WHERE UPPER("Name") = 'PROGA.H' AND UPPER("Source") = "..."

SELECT ObjectId, Name..... FROM tblRegisteredIncludes   
WHERE UPPER("Name") = ('PROGB.H') AND UPPER("Source") = "..."

我已将tblRegisteredIncludes表中的 Name-Index 替换为(Name,Source).

即使如此,我也预计 SQL 的总执行速度会慢一些,但不会超过 15-20%。相反,它要慢得多,有时甚至高达 100%。我尝试使用 UNION ALL 将 SQL 组合在一个大型 SQL 查询中:

SELECT ObjectId, Name..... FROM tblRegisteredIncludes   
WHERE UPPER("Name") = 'PROGA.H' AND UPPER("Source") = "..."
UNION ALL
SELECT ObjectId, Name..... FROM tblRegisteredIncludes   
WHERE UPPER("Name") = ('PROGB.H') AND UPPER("Source") = "..."

然后稍后处理生成的 ADO DB 记录集,但速度更慢!

我需要知道是否有一些有效的方法可以更快地执行这些查询?在使用 IN 子句和名称列表时,我需要达到与旧案例类似的性能。我可以提供执行计划。

4

2 回答 2

3

在该union all版本中,每个子查询都会导致对表的单独扫描。

您应该使用or条件引入所有行:

SELECT ObjectId, Name.....
FROM tblRegisteredIncludes   
WHERE (UPPER("Name") = 'PROGA.H' AND UPPER("Source") = "...") or
      (UPPER("Name") = ('PROGB.H') AND UPPER("Source") = "...") or
      . . .

如果您遇到所有比较都打开Name和的情况Source,我建议您使用 CTE 创建一个动态表:

with toinclude as (
   select 'PROGA.H' as name, 'SOURCE' as source union all
   select . . .
)
select ri.ObjectId, ri.Name
from tblRegisteredIncludes join
     toinclude
     on ri.name = toinclude.name and ri.source = toinclude.source

您可以省略toupper()除非您​​特别担心您的实现或字段已覆盖默认的不区分大小写行为。在子句中使用函数where通常会阻止使用索引。

于 2013-03-21T13:10:19.080 回答
0

根据您的描述,我假设该表具有大量行,在这种情况下,几乎可以肯定是 UPPER 导致了速度问题,因为这意味着它无法正确使用您似乎已正确设置的索引。存储的数据真的区分大小写吗?- 检查 db 设置,默认情况下通常不会,在这种情况下您可以删除 UPPER。

如果它是区分大小写的,那么如果存储名称的大小写是一致的,您仍然可以删除大写并只使用一致的大写/小写名称,例如 Name = 'ProgB.H'

于 2013-03-21T12:48:37.423 回答