1

我有一个查询似乎需要很长时间才能执行。自从我做了非常简单的选择/更新和 v.simple 连接之外的任何事情已经有一段时间(几年)了,所以我在这里有点生疏了!

SELECT count(distinct r.TAGCODE)
FROM RAWREADS r
where r.TAGCODE NOT IN (
    select distinct r.TAGCODE 
    from RAWREADS r, checkpoints c, guards g, INCIDENTITEMS i
        where r.TAGCODE = c.TAGNO
        or    r.TAGCODE = g.IDTAG
        or    r.TAGCODE = i.IDTAG
    );

如果缓慢(几秒钟),内部选择似乎可以正常工作,但是一旦我添加外部“不在其中的计数”,我最终不得不终止我的数据库连接 - 所以对应用程序没有好处!;)

我希望上面的查询清楚我想要实现的目标...获取所有 rawread 标记,其中该标记与检查点/警卫/事件中的相应列不匹配。

如果这很重要,我正在使用 Flamebird 数据库服务器(没有选择)和 FlameRobin 来运行查询。

在某些时候,我还需要向外部选择添加一个查询,以确保我不会选择任何标记代码为空或“”的 rawreads。

我已经从 out select 中删除了“char_length(tagcode) > 0”标准,希望加快速度,但我认为我的问题比这更根本。

4

5 回答 5

3

许多数据库(可能还有 Firebird)无法轻松优化 NOT IN 条件。因此,您可能会尝试将其重写为 NOT EXTISTS。

另外看看内部选择,我认为你加入的方式产生了太多的行。这不是真正的连接,但也不是笛卡尔积。无论如何,我可以想象在那里做一个 UNION 也更有效率。

所以试试这个:

SELECT count(distinct r.TAGCODE)
FROM RAWREADS r
where NOT EXISTS (
    select 1
    from checkpoints c
    where c.tagno = r.tagcode
    union all
    select 1 
    from guards g
    where g.idtag = r.tagcode
    union all 
    select 1 
    from INCIDENTITEMS i
    where i.idtag = r.tagcode);

如果你有索引checkpoints(tagno)guards(idtag)incidentitems(idtag)应该运行得相当快。

于 2012-08-08T13:45:43.933 回答
2

NOT IN将为其中的每一行调用内部子查询RAWREADS,因此该查询运行缓慢。如果您作为过程运行,则将子查询结果转储到临时表中并与该临时表进行内部连接并执行否定条件TAGCODE

于 2012-08-08T13:42:16.210 回答
1
SELECT count(distinct r.TAGCODE)
FROM RAWREADS r
where NOT EXISTS (
    select *  
    from  checkpoints c, guards g, INCIDENTITEMS i
        where r.TAGCODE = c.TAGNO
        or    r.TAGCODE = g.IDTAG
        or    r.TAGCODE = i.IDTAG
    );

如果 sql 服务器

SELECT count(distinct r.TAGCODE)
FROM RAWREADS r
where NOT EXISTS (
    select TOp 1 1   
    from  checkpoints c, guards g, INCIDENTITEMS i
        where r.TAGCODE = c.TAGNO
        or    r.TAGCODE = g.IDTAG
        or    r.TAGCODE = i.IDTAG
    );
于 2012-08-08T13:42:19.977 回答
0

下面的代码与 Firebird 2.5 兼容,而且速度很快。我现在无法测试它,但这是我的想法。它使用 CTR 来简化子查询代码。

with SQ1 as (
  select distinct r.TAGCODE as TAGCODE
  from RAWREADS r, checkpoints c, guards g, INCIDENTITEMS i
      where r.TAGCODE = c.TAGNO
      or    r.TAGCODE = g.IDTAG
      or    r.TAGCODE = i.IDTAG
)

SELECT count(distinct r.TAGCODE)
FROM RAWREADS r
left join SQ1 on (r.TAGCODE = SQ1.TAGCODE)
where SQ1.TAGCODE is NULL
于 2012-08-08T14:30:45.567 回答
0

在几乎所有 RDBMS 中,获得优化的 NOT IN 子句的最佳方法是在 WHERE 子句中编写带有失败条件的 LEFT OUTER JOIN,如下所示:

SELECT count(distinct r.TAGCODE)
FROM RAWREADS r
left outer join checkpoints c on r.TAGCODE = c.TAGNO
left outer join guards g on r.TAGCODE = g.IDTAG
left outer join INCIDENTITEMS i on r.TAGCODE=i.IDTAG
where 
  c.TAGNO is null AND
  g.IDTAG is null AND
  i.IDTAG is null

从一般的角度来看,NOT IN 子句如下:

select * from TABLEA 
where TABLEA.ID NOT IN (SELECT ID from TABLEB)

可以成功转换为

select TABLEA.*
from TABLEA 
left outer join TABLEB ON TABLEA.ID=TABLEB.ID
where TABLEB.ID is null

如果 TABLEB 在列 ID 上有一个索引,则查询在从 TABLEA 中检索所有在 TABLEB 中没有对应项的记录方面非常快

于 2012-08-09T10:09:33.763 回答