【发布时间】:2017-07-24 11:41:52
【问题描述】:
我在 Postgresql 中的查询遇到了一些问题。此查询需要很长时间才能执行(大约 30 秒没有缓冲区) 我的查询在这里:
SELECT d.name, COUNT (*) AS cnt,
'first' AS TYPE
FROM
tableA a
INNER JOIN tableD d ON d.NAME = 'FOO'
AND a.key = d.key
WHERE
a.DATE > '2017-06-01'
AND a.DATE < '2017-07-01'
group by d.name
UNION ALL
SELECT
d.name,
COUNT (*) AS cnt,
'second' AS TYPE
FROM
tableB b
INNER JOIN tableD d ON d.NAME = 'FOO'
AND b.key = d.key
WHERE
b.DATE > '2017-06-01'
AND b.DATE < '2017-07-01'
group by d.name
UNION ALL
SELECT
d.name,
COUNT (*) AS cnt,
'Third' AS TYPE
FROM
tableC c
INNER JOIN tableD d ON d.NAME = 'FOO'
AND c.key = d.key
WHERE
c.date > '2017-06-01'
AND c.date < '2017-07-01'
group by d.name
我在 tableC.key (Btree) 和 tableC.name (Hash) 上创建了索引 此外,其他表具有日期和键(Btree)索引
所以我的查询可以按索引加入,并且可以按索引过滤
我的 tableD 有几千行,其他有数十亿或几乎数十亿
在执行计划中,我看到执行程序使用嵌套循环所有我的连接(期望在 B-D 连接处有一个,有一个哈希连接)
也许我找到了“背叛者”
Node Type": "Bitmap Heap Scan",
"Parent Relationship": "Inner",
"Relation Name": "tableA",
"Alias": "a",
"Startup Cost": 2469.84,
"Total Cost": 137625.61,
"Plan Rows": 53748,
"Plan Width": 37,
"Recheck Cond": "(((key)::text = (d.key)::text) AND (date > '2017-06-01 00:00:00'::timestamp without time zone) AND (date < '2017-07-01 00:00:00'::timestamp without time zone))",
"Plans": [{
"Node Type": "Bitmap Index Scan",
"Parent Relationship": "Outer",
"Index Name": "\"date + key\"",
"Startup Cost": 0.00,
"Total Cost": 2456.40,
"Plan Rows": 53748,
"Plan Width": 0,
"Index Cond": "(((key)::text = (d.key)::text) AND (date > '2017-06-01 00:00:00'::timestamp without time zone) AND (date < '2017-07-01 00:00:00'::timestamp without time zone))"
}]
表D:
CREATE TABLE "sch"."tableD" (
"id" int4 NOT NULL,
"key" varchar(36) COLLATE "default",
"name" varchar(255) COLLATE "default",
CREATE INDEX "license_key" ON "sch"."tableD" USING btree ("key");
CREATE INDEX "name" ON "sch"."tableD" USING btree ("name");
表A:
CREATE TABLE "sch"."tableA" (
"id" int4 DEFAULT nextval('"sch".table'::regclass) NOT NULL,
"key" varchar(255) COLLATE "default",
"date" timestamp(6),
CREATE INDEX "date" ON "sch"."tableA" USING btree ("date");
CREATE INDEX "date + key" ON "sch"."tableA" USING btree ("key", "date")
CREATE INDEX "keyIndex" ON "sch"."tableA" USING btree ("key");
TableB 和 C 类似于 A
我不知道,为什么我会在这里浪费时间。你能帮我解决我的问题吗,这个查询不应该运行 30 秒 谢谢
【问题讨论】:
-
首先测量每个子查询需要多长时间。然后您可以缩小性能问题的范围。
-
不确定,但在我看来,我们可以消除联合并使用窗口函数进行 1 个查询来获取计数。以及用于设置类型和外连接的 case 语句。
-
第一个子查询花费的时间最长,但大多数行都在 tableA 中,所以我可以想象这可能会导致查询速度变慢如果我消除我的联合,执行程序可以选择散列连接(或者合并连接,如果我在键上使用哈希索引),但速度更慢(100-120 秒)
-
d.key可以存在于A,b,C多个表中吗?
-
请Edit您的问题并为有问题的表(包括所有索引)添加
create table语句,使用explain (analyze, verbose)生成的执行计划(文本格式,请不要使用json、xml或yaml)。
标签: sql postgresql optimization query-optimization