查询优化,问题

Query Optimization, Issue

使用 SQL 服务器 2012;

我正在使用查询在 table 中查找增量。 我有一个存档 table,其中包含所有带有 Licenceno PK、FileID

的记录

我想知道有多少个 Licenceno 在一个 fileId 中,但不在以前的 FileID 中。

使用的代码:

Select count(*) from table where fileid = 123 and Licenceno not in (select Licenceno from table where fileid <123)

代码工作正常,但问题是一些 fileIds 的记录数与之前的相同,但需要 4 个小时,并且仍然 运行..

  1. 这是 table 问题吗?
  2. 索引不会成为问题,因为整个 table 都有 非聚集索引。
  3. 当我计算最新 Licenceno 的增量时,通常会发生这种情况。
  4. 或者查询计划是问题所在?

过去 5 天我都无法解决这个问题。

我会重写您的查询以使用 exists 子句,并添加适当的索引:

SELECT COUNT(*)(
FROM yourTable t1
WHERE
    fileid = 123 AND
    NOT EXISTS (SELECT 1 FROM yourTable t2
                WHERE t2.Licenseno = t1.Licenseno AND t2.fileid < 123);

(Licenseno, fileid) 上的索引可能对此处有所帮助:

CREATE INDEX idx ON yourTable (Licenseno, fileid);

你也可以按相反的顺序试试came复合索引:

CREATE INDEX idx ON yourTable (fileid, Licenseno);

为什么不使用 count(distinct)

select count(distinct licenseno)
from table
where fileid = 123;

对于此查询,您需要 (fileid, licenseno) 上的索引。

您按顺序思考会使逻辑复杂化 ("have I seen this licenseno already?")。相反,您只想计算不同的值。

编辑:

对于这个问题,可以尝试两级聚合:

select count(*)
from (select licenseno, min(fileid) as min_fileid
      from t
      where licenseno <= 123
      group by licenseno
     ) t
where min_fileid = 123;

相对于其他方法的性能有多好取决于 <= 123 的选择性。

您也可以使用 LAG

SELECT COUNT(*)
FROM   (SELECT fileid,
               LAG(fileid) OVER (PARTITION BY Licenceno ORDER BY fileid) AS prevFileID
        FROM   TABLE
        WHERE  fileid <= 123 ) D
WHERE  fileid = 123
       AND prevFileID IS NULL 

...或聚合查询...

WITH T
     AS (SELECT 1 AS Flag,
         FROM   TABLE
         WHERE  fileid <= 123         
         GROUP  BY Licenceno
         HAVING MIN(fileid) = 123 )
SELECT COUNT(*)
FROM   T