我有一个查询,它消耗大量CPU,导致某些超时:
select cast(count(*) as INT) as colCount
from TableGR tgr
where ((tgr.OriginCode is not null)
and (tgr.OriginCode in (@p0 , @p1 , @p2 , @p3))
or tgr.Type=@p4
and (tgr.OriginVat in (@p5 , @p6 , @p7 , @p8))
or (tgr.DestinCode is not null)
and (tgr.DestinCode in (@p9 , @p10 , @p11 , @p12))
or (exists (select t1.Id
from Transporters t1
where tgr.GarId=t1.GarId))
and (exists (select t2.Id
from Transporters t2
where tgr.GarId=t2.GarId and (t2.Vat in (@p13 , @p14 , @p15 , @p16))))
)
and (tgr.DeletedUtc is null);
我想查询是执行多个子查询的原因,因此我考虑向表TableGR添加新列,以包含用逗号分隔的字符串t1.Id和t2.Id。我考虑的另一种选择是在表TableGR中添加两个新列(列t1Id,t2Id)。
答案 0 :(得分:0)
您可以将查询更改为使用联接,而不是使用联接来优化查询。
我考虑将新列添加到表TableGR中,以包含一个逗号分隔的字符串,其中包含t1.Id和t2.Id`
我考虑的另一种选择是在表TableGR中添加两个新列(列t1Id,t2Id)
有太多可能的优化方法,根据您的数据,这些优化方法可能会也可能无法帮助您。这就是为什么最好使用view query execution plan
查看执行查询所花费的时间最多的时间答案 1 :(得分:0)
如果重新格式化您的查询,可以看到它是由许多不同列上的搜索组成的。这使得优化器很难利用任何索引。
select
cast(count(*) as INT) as colCount
from
TableGR tgr
where
(
(tgr.OriginCode is not null)
and (tgr.OriginCode in (@p0 , @p1 , @p2 , @p3))
or
tgr.Type=@p4
and (tgr.OriginVat in (@p5 , @p6 , @p7 , @p8))
or
(tgr.DestinCode is not null)
and (tgr.DestinCode in (@p9 , @p10 , @p11 , @p12))
or
(exists (select t1.Id from Transporters t1 where tgr.GarId=t1.GarId))
and (exists (select t2.Id from Transporters t2 where tgr.GarId=t2.GarId and (t2.Vat in (@p13 , @p14 , @p15 , @p16))))
)
and
(tgr.DeletedUtc is null);
一种 的缓解方法是将其分解为可以使用表索引的简单查询。
(我将x IS NOT NULL AND x IN (a,b,c)
简化为x IN (a,b,c)
,因为如果x为null,则它永远不会出现在任何列表中……)
SELECT
COUNT(*) AS colCount
FROM
(
-- Could use an index on (DeletedUtc, OriginCode)
SELECT PrimaryKeyColumn
FROM TableGR tgr
WHERE tgr.DeletedUtc IS NULL
AND tgr.OriginCode in (@p0 , @p1 , @p2 , @p3)
UNION
-- Could use an index on (DeletedUtc, Type, OriginCode)
SELECT PrimaryKeyColumn
FROM TableGR tgr
WHERE tgr.DeletedUtc IS NULL
AND tgr.Type=@p4
AND tgr.OriginVat in (@p5 , @p6 , @p7 , @p8)
UNION
-- Could use an index on (DeletedUtc, DestinCode)
SELECT PrimaryKeyColumn
FROM TableGR tgr
WHERE tgr.DeletedUtc IS NULL
AND tgr.DestinCode in (@p9 , @p10 , @p11 , @p12)
UNION
-- Could use an index on (DeletedUtc, GarID)
SELECT PrimaryKeyColumn
FROM TableGR tgr
WHERE tgr.DeletedUtc IS NULL
-- Why the Two EXISTS() expressions here? If the second is TRUE the first is always also TRUE, no?
AND (exists (select t1.Id from Transporters t1 where tgr.GarId=t1.GarId))
AND (exists (select t2.Id from Transporters t2 where tgr.GarId=t2.GarId and (t2.Vat in (@p13 , @p14 , @p15 , @p16))))
)
AS targets
请注意,我使用的是UNION
而不是UNION ALL
。这是为了防止一行可以满足一项条件(UNION
“对数据进行重复数据删除”,从而防止对一行进行多次计数。)
如果您 知道 ,任何一行只能出现在 单 查询中,请使用{{ 1}}。
然后返回您的执行计划,看看是否还有其他索引或其他优化可能会有所帮助。