6

私のサーバーでこのクエリを実行すると、非常に遅くなり、理由がわかりません。誰かが私がそれを理解するのを手伝ってもらえますか?
クエリ:

SELECT
    "t_dat"."t_year" AS "c0",
    "t_dat"."t_month" AS "c1",
    "t_dat"."t_week" AS "c2",
    "t_dat"."t_day" AS "c3",
    "t_purs"."p_id" AS "c4",
    sum("t_purs"."days") AS "m0",
    sum("t_purs"."timecreated") AS "m1"
FROM "t_dat", "t_purs"
WHERE "t_purs"."created" = "t_dat"."t_key"
  AND "t_dat"."t_year" = 2013
  AND "t_dat"."t_month" = 3
  AND "t_dat"."t_week" = 9
  AND "t_dat"."t_day" IN (1,2)
  AND "t_purs"."p_id" IN (
      '4','15','18','19','20','29',
      '31','35','46','56','72','78')
GROUP BY
    "t_dat"."t_year",
    "t_dat"."t_month",
    "t_dat"."t_week",
    "t_dat"."t_day",
    "t_purs"."p_id"

分析の説明:

HashAggregate(cost = 12252.04..12252.04 rows = 1 width = 28)(actualtime = 10212.374..10212.384 rows = 10 loops = 1)
  ->ネストされたループ(コスト=0.00..12252.03行=1幅=28)(実際の時間=3016.006..10212.249行=14ループ=1)
        参加フィルター:(t_dat.t_key = t_purs.created)
        -> t_datでのシーケンススキャン(コスト=0.00..129.90行=1幅=20)(実際の時間=0.745..2.040行=48ループ=1)
              フィルタ:((t_day = ANY('{1,2}' :: integer []))AND(t_year = 2013)AND(t_month = 3)AND(t_week = 9))
        -> t_pursでのシーケンススキャン(コスト=0.00..12087.49行=9900幅=16)(実際の時間=0.018..201.630行=14014ループ=48)
              フィルタ:(p_id = ANY('{4,15,18,19,20,29,31,35,46,56,72,78}' :: integer []))
合計実行時間:10212.470ミリ秒
4

3 に答える 3

8

何が欠けているのかを正確に言うのは難しいですが、私があなたなら、次のインデックスが存在することを確認します。

CREATE INDEX t_dat_id_date_idx
    ON t_dat (t_key, t_year, t_month, t_week, t_day);

の場合t_purs、次のインデックスを作成します。

CREATE INDEX t_purs_created_p_id_idx
    ON t_purs (created, p_id);
于 2013-03-03T19:36:29.363 に答える
1

テーブルで単一の列を使用することを検討してください。

t_date date

の代わりに(t_year, t_month, t_week, t_day)。データ型dateは4バイトを占めます。これにより、テーブルが少し縮小され、インデックスがより小さく、より速くなり、グループ化がはるかに簡単になります。

は、日付から簡単かつ迅速に抽出できますextract()。その場合、クエリは次のようになり、より高速になります。

SELECT extract (year  FROM t_date) AS c0
      ,extract (month FROM t_date) AS c1
      ,extract (week  FROM t_date) AS c2
      ,extract (day   FROM t_date) AS c3
      ,p.p_id                      AS c4
      ,sum(p.days)                 AS m0
      ,sum(p.timecreated)          AS m1
FROM   t_dat  d
JOIN   t_purs p ON p.created = d.t_key
WHERE  d.t_date IN ('2013-03-01'::date, '2013-03-02'::date)
AND    p.p_id IN (4,15,18,19,20,29,31,35,46,56,72,78)
GROUP  BY d.t_date, p.p_id;

パフォーマンスにとってより重要なのはインデックスです。これは単純に次のようになります。

CREATE INDEX t_dat_date_idx ON t_dat (t_key, t_date);

または、データの分散に応じて:

CREATE INDEX t_dat_date_idx ON t_dat (t_date, t_key);

列の順序が重要です。両方を作成することもできます。

于 2013-03-04T04:30:51.593 に答える
1

ここに画像の説明を入力してください

クエリはとで順次スキャンを実行していt_pursますt_dat。適切なインデックスを作成すると、このクエリを高速化し、順次スキャンを回避するのに役立ちます。

create index index_name on t_purs(created) where created is not null;
create index index_name on t_dat using btree(t_key, t_year, t_month, t_week, t_day)

上記の2つのクエリを実行した後、explainanalyzeを実行します。計画時間と実行時間が短縮されます。

于 2022-02-06T21:02:53.310 に答える