Sql 性能显著下降,情况应评估一次
我有一个问题,添加一个简单的测试条件(应该是 每个查询只计算一次)整个查询中的结果将使用十次 只要能回来。我正在运行PostgreSQL 9.2,正在使用的表是 详情如下:Sql 性能显著下降,情况应评估一次,sql,postgresql,Sql,Postgresql,我有一个问题,添加一个简单的测试条件(应该是 每个查询只计算一次)整个查询中的结果将使用十次 只要能回来。我正在运行PostgreSQL 9.2,正在使用的表是 详情如下: CREATE TABLE tags ( tid int4 UNIQUE NOT NULL, name text UNIQUE NOT NULL, PRIMARY KEY (tid)); CREATE TABLE bugs ( bid int4 UNIQUE NOT NU
CREATE TABLE tags (
tid int4 UNIQUE NOT NULL,
name text UNIQUE NOT NULL,
PRIMARY KEY (tid));
CREATE TABLE bugs (
bid int4 UNIQUE NOT NULL,
type int2 NOT NULL,
title text NOT NULL,
PRIMARY KEY (bid));
CREATE TABLE bug_tags (
bid int4 REFERENCES bugs(bid) NOT NULL,
tid int4 REFERENCES tags(tid) NOT NULL,
PRIMARY KEY (bid, tid));
CREATE INDEX bug_tags_bid_idx ON bug_tags (bid);
CREATE INDEX bug_tags_tid_idx ON bug_tags (tid);
查询必须返回按bid排序的前20个匹配错误,其中
匹配的条件是bug的类型必须符合提供的
位掩码(变量$TYPE)以及与错误相关联的标记集必须
是所提供的一组标记名的超集(在
准备好的声明)。在尝试了几种方法之后,下面是一种
这会产生最好的结果。其基本思想是首先获取所有
满足$TAGNAMES条件的bug,然后测试每个bug的
$TYPE条件。此外,如果$TAGNAMES为空,那么我们将跳过抓取
这些错误,而不是专注于在整个表中循环
(因为我们只需要前20行,所以这应该快得多)。
后一种测试是导致令人困惑的结果的测试
WITH tids AS
(SELECT tid
FROM tags
WHERE name = ANY ($TAGNAMES :: text[])),
bugs_from_tags AS
(SELECT DISTINCT t1.bid
FROM bug_tags AS t1
WHERE NOT EXISTS
(SELECT *
FROM tids
WHERE NOT EXISTS
(SELECT *
FROM bug_tags AS t2
WHERE t2.tid = tids.tid AND t2.bid = t1.bid)))
SELECT bid, type, title
FROM bugs
WHERE (type & $TYPE <> 0) AND
(($TAGNAMES :: text[]) = '{}' OR bid IN (SELECT * FROM bugs_from_tags))
ORDER BY bid
LIMIT 20;
显然,当len($TAGNAMES)出现时,添加测试条件会获得丰厚的回报=
0,否则将导致灾难。这是令人费解的,因为条件
独立于每行,因此只应计算一次。
此外,解释分析(相当长)的结果确实表明
在len($TAGNAMES)=1的情况下使用/不使用的计划是
非常不同,尽管它们应该是相同的
无论如何,我怀疑我偶然发现了PostgreSQL查询的一个怪癖(或bug?)
计划者。有什么办法可以绕过它吗
注意:两项测试的解释分析结果如下:
而且。阅读计划时,主要区别在于快速计划首先过滤结果,然后将其合并。第二个过滤器和嵌套循环联接 关于这个缓慢的查询,有两件事让我印象深刻 首先,它选择了一个糟糕的计划。当您没有足够的内存来确保另一个计划更好时,可能会发生这种情况。尝试将有效缓存大小设置得更高一点,并将工作内存设置得更高一点 第二个问题是,慢速查询缺少哈希聚合。我建议将DISTINCT改为GROUP BY,看看这是否有帮助。我的猜测是,在慢循环中,它可能是具体化了CTE,然后将查询作为嵌套循环对其运行
然而,除了这些,以及可能在系统中添加更多内存之外,我看不到任何让我印象深刻的即时答案。我希望这是有帮助的,如果您在这里无法获得帮助,PostgreSQL上的-perform列表通常非常善于帮助人们。您能发布
解释分析的输出吗?(理想情况下)查询的主要部分中的括号似乎不平衡。这可能与AND/OR组合有关。@DanielVérité:我已经修复了不平衡的括号。这只是一个复制/粘贴问题;最初的查询是正确的,因此这不是问题所在。@a_horse_,没有名称:我已经添加了EXPLAIN ANALYZE的结果。查看计划的底部-速度慢的计划已决定循环输入。。。来自标签扫描的错误。我猜这和手术室有关
WHERE (type & $TYPE <> 0) AND (bid IN (SELECT * FROM bugs_from_tags))
with without
len($TAGNAMES) = 0: 4 1500
len($TAGNAMES) = 1: 13000 1600