If I reformat your query I can see that it is made from searches on many different columns. That makes it very hard for an optimiser to make use of any indexes.
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);
One way to mitigate that is to break it into simpler queries that can make use of indexes on your table.
(I've simplified x IS NOT NULL AND x IN (a,b,c)
to x IN (a,b,c)
, because if x is null then it's never in any list...)
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
Note that I've used UNION
rather than UNION ALL
. This is incase one row can fulfil more that one of the criteria (UNION
"de-duplicates" the results, preventing one row being counted multiple times.)
If you know that any one row can only be present in a single query, use UNION ALL
instead.
Then go back to your execution plan and see if there are any other indexes or other optimisations that may help.