2017-12-28 19 views
0

を選ぶなぜ私はこのクエリは少ないし、100ミリ秒で高速に実行されますが、時にはそれは非常に、いくつかのc_phone2のために4秒にid_organizationの組み合わせを遅く実行を開始する時間のほとんどは、単純なクエリPostgresが間違った実行計画

select count(*) 
from taxi_order.ta_orders o 
    inner join public.t_bases b on b.id = o.id_base 
where o.c_phone2 = '' 
    and b.id_organization = 1 
    and o.c_date_end < '2017-12-01'::date 
group by date_trunc('month', o.c_date_end); 

を持っています。速い場合の

実行計画:遅い場合の

HashAggregate (cost=7005.05..7005.62 rows=163 width=8) 
    Group Key: date_trunc('month'::text, o.c_date_end) 
    -> Hash Join (cost=94.30..7004.23 rows=163 width=8) 
     Hash Cond: (o.id_base = b.id) 
     -> Index Scan using ix_ta_orders_c_phone2 on ta_orders o (cost=0.57..6899.41 rows=2806 width=12) 
       Index Cond: ((c_phone2)::text = $3) 
       Filter: (c_date_end < $4) 
     -> Hash (cost=93.26..93.26 rows=133 width=4) 
       -> Bitmap Heap Scan on t_bases b (cost=4.71..93.26 rows=133 width=4) 
        Recheck Cond: (id_organization = $2) 
        -> Bitmap Index Scan on ix_t_bases_id_organization (cost=0.00..4.68 rows=133 width=0) 
          Index Cond: (id_organization = $2) 

実行計画:

HashAggregate (cost=6604.97..6604.98 rows=1 width=8) 
    Group Key: date_trunc('month'::text, o.c_date_end) 
    -> Nested Loop (cost=2195.33..6604.97 rows=1 width=8) 
     -> Bitmap Heap Scan on t_bases b (cost=2.29..7.78 rows=3 width=4) 
       Recheck Cond: (id_organization = $2) 
       -> Bitmap Index Scan on ix_t_bases_id_organization (cost=0.00..2.29 rows=3 width=0) 
        Index Cond: (id_organization = $2) 
     -> Bitmap Heap Scan on ta_orders o (cost=2193.04..2199.06 rows=3 width=12) 
       Recheck Cond: (((c_phone2)::text = $3) AND (id_base = b.id) AND (c_date_end < $4)) 
       -> BitmapAnd (cost=2193.04..2193.04 rows=3 width=0) 
        -> Bitmap Index Scan on ix_ta_orders_c_phone2 (cost=0.00..58.84 rows=3423 width=0) 
          Index Cond: ((c_phone2)::text = $3) 
        -> Bitmap Index Scan on ix_ta_orders_id_base_date_end (cost=0.00..2133.66 rows=83472 width=0) 
          Index Cond: ((id_base = b.id) AND (c_date_end < $4)) 

クエリかんなは時々とても遅い無効計画を選択しますなぜ?テーブル用

EDIT

スキーマ:

craete table taxi_order.ta_orders (
    id bigserial not null, 
    id_base integer not null, 
    c_phone2 character varying(30), 
    c_date_end timestamp with time zone, 
... 
    CONSTRAINT pk_ta_orders PRIMARY KEY (id), 
    CONSTRAINT fk_ta_orders_t_bases REFERENCES public.t_bases (id) 
); 

craete table public.t_bases (
    id serial not null, 
    id_organization integer not null, 
... 
    CONSTRAINT pk_t_bases PRIMARY KEY (id) 
); 

ta_orders〜100Mの行は、〜2K行をt_bases。

EDIT2

遅い場合のために、分析説明:私はそれをスピードアップするためにすべてのクエリのために別のインデックスを作成することができます知っている

HashAggregate (cost=7005.05..7005.62 rows=163 width=8) (actual time=0.927..0.928 rows=1 loops=1) 
    Group Key: date_trunc('month'::text, o.c_date_end) 
    -> Hash Join (cost=94.30..7004.23 rows=163 width=8) (actual time=0.903..0.913 rows=2 loops=1) 
     Hash Cond: (o.id_base = b.id) 
     -> Index Scan using ix_ta_orders_c_phone2 on ta_orders o (cost=0.57..6899.41 rows=2806 width=12) (actual time=0.591..0.604 rows=4 loops=1) 
       Index Cond: ((c_phone2)::text = $3) 
       Filter: (c_date_end < $4) 
       Rows Removed by Filter: 2 
     -> Hash (cost=93.26..93.26 rows=133 width=4) (actual time=0.237..0.237 rows=133 loops=1) 
       Buckets: 1024 Batches: 1 Memory Usage: 13kB 
       -> Bitmap Heap Scan on t_bases b (cost=4.71..93.26 rows=133 width=4) (actual time=0.058..0.196 rows=133 loops=1) 
        Recheck Cond: (id_organization = $2) 
        Heap Blocks: exact=45 
        -> Bitmap Index Scan on ix_t_bases_id_organization (cost=0.00..4.68 rows=133 width=0) (actual time=0.044..0.044 rows=133 loops=1) 
          Index Cond: (id_organization = $2) 

HashAggregate (cost=6355.29..6355.29 rows=1 width=8) (actual time=4075.847..4075.847 rows=1 loops=1) 
    Group Key: date_trunc('month'::text, o.c_date_end) 
    -> Nested Loop (cost=2112.10..6355.28 rows=1 width=8) (actual time=114.871..4075.803 rows=2 loops=1) 
     -> Bitmap Heap Scan on t_bases b (cost=2.29..7.78 rows=3 width=4) (actual time=0.061..0.375 rows=133 loops=1) 
       Recheck Cond: (id_organization = $2) 
       Heap Blocks: exact=45 
       -> Bitmap Index Scan on ix_t_bases_id_organization (cost=0.00..2.29 rows=3 width=0) (actual time=0.045..0.045 rows=133 loops=1) 
        Index Cond: (id_organization = $2) 
     -> Bitmap Heap Scan on ta_orders o (cost=2109.81..2115.83 rows=3 width=12) (actual time=30.638..30.638 rows=0 loops=133) 
       Recheck Cond: (((c_phone2)::text = $3) AND (id_base = b.id) AND (c_date_end < $4)) 
       Heap Blocks: exact=2 
       -> BitmapAnd (cost=2109.81..2109.81 rows=3 width=0) (actual time=30.635..30.635 rows=0 loops=133) 
        -> Bitmap Index Scan on ix_ta_orders_c_phone2 (cost=0.00..58.85 rows=3427 width=0) (actual time=0.032..0.032 rows=6 loops=133) 
          Index Cond: ((c_phone2)::text = $3) 
        -> Bitmap Index Scan on ix_ta_orders_id_base_date_end (cost=0.00..2050.42 rows=80216 width=0) (actual time=30.108..30.108 rows=94206 loops=133) 
          Index Cond: ((id_base = b.id) AND (c_date_end < $4)) 

が速い場合のために、分析を説明してください。しかし、私は間違った計画を選ぶ理由は何かを知りたいですか?私の統計に何が間違っていますか?

+0

もっと詳しい情報が必要だと思います。これらの2つのテーブルのスキーマは何ですか? –

答えて

2

明確な回答を得るには、EXPLAIN (ANALYZE, BUFFERS)の出力を与える必要があります。

計画の違いは、2番目のプランが入れ子になったループ結合を選択することです。これは、ほんのわずかの行だけがt_basesから選択されると推定するためです。クエリが遅いと不平を言いますので、その推定値は間違っている可能性があります。その結果、内部テーブルに対してループが多すぎます。

default_statistics_targetを増やした後に、ANALYZEを実行してテーブルの統計情報を改善してください。

ta_orders(c_phone2, id_base, c_date_end)のマルチカラムインデックスは、ネストされたループプランの実行時間を改善します。

+0

私は私の質問に分析結果を追加しました。この行にはかなりの行見積もりエラーがあります。 'Bitmap Index Scan on ix_t_bases_id_organization(コスト= 0.00..2.29行= 3幅= 0)(実際の時間= 0.045..0.045行= 133ループ= 1)'。間違った計画を選んだ理由はありますか? –

+0

はい、それは確かに理由です。 'ANALYZE'を実行してみてください。十分な統計量を得るために 'ANALYZE'に対して' default_statistics_target'を増やす必要があるならば、 'ALTER TABLE t_base ALTER id_organization SET STATISTICS 1000;'(またはそれ以上)で設定を永久にすることができます。 –

0

わかりませんが、私はあなたのクエリに改善の可能性を示唆しています:内部結合を削除してください。あなたはそのテーブルから何も選択していないので、なぜそれを照会するのが気になるのですか?クエリにwhere o.id_base = ?を追加できるはずです。

ta_orders(id_base, c_phone2, c_date_end)に次のインデックスを追加するたびに、このクエリをすばやく実行したい場合。 >または< where句が最後にある列が重要です(そうしないと、Postgresはそれを使用できなくなります)。

+0

はい、どこにo.id_base(public.t_baseからidを選んでid_organization =?) 'を追加できますが、これはまったく同じ計画を与えます。 c_phone2、c_date_end、id_base、(id_base、c_date_end)にインデックスがあります。Plannerは、遅い計画でix_ta_orders_id_base_date_endを使用することに決めました。 IMHOこれは間違った決定です。なぜなら、このインデックスは行の見積もりに従ってix_ta_orders_c_phone2よりはるかに選択的ではないからです。 –

関連する問題