【问题标题】:Postgresql LARGE query optimizationPostgresql LARGE 查询优化
【发布时间】: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


【解决方案1】:

提供这些BTree索引(哈希):

b: (DATE, key)
b: (key, DATE)
d: (NAME, key)
d: (key, NAME)

看起来像是一个月的时间跨度,但您排除了月初。将&gt; 更改为&gt;=

【讨论】:

    猜你喜欢
    • 2014-06-13
    • 2022-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-12
    • 2018-02-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多