ウィザードがあります。 次のSQLクエリの奇妙なパフォーマンスで私の頭が壊れています。それは私がテーブルに置かれるデータの量を計算するのに約10秒かかります入れ子になったクエリを最適化して、驚異的なパフォーマンスを避けてください
WITH temp_song_id_with_all_stemmed_words AS
(SELECT song_id FROM stemmed_words
WHERE stemmed_word IN ('yesterdai','troubl','seem','awai','believ')
GROUP BY song_id
HAVING COUNT(*)=5)
SELECT *
FROM words
WHERE song_id IN(
SELECT song_id
FROM temp_song_id_with_all_stemmed_words
)
ORDER BY song_id, global_position;
: は、私はSQLコード(PG上で実行されている)を、以下で構成されている次のクエリを持っています。その後、
-
一時テーブル内の句「と」置くクエリ自体
- 内部の句「と」入れ
- とそれに
- インデックスを照会: 私はこのクエリを最適化するために、様々なアプローチを試してみました可能なすべての列
しかし、それは役に立たなかった。計算時間はまだ約10秒です(すべてがすでにメモリにキャッシュされていると仮定しても、1分もかかることはありません)
次に、物事は全く異なる振る舞いを構成する部品:
SELECT song_id FROM stemmed_words
WHERE stemmed_word IN ('yesterdai','troubl','seem','awai','believ')
GROUP BY song_id
HAVING COUNT(*)=5
このクエリはトップスを計算するのに約500ミリ秒かかり、そして3つのidを与え、結果として
を私は外側のクエリを計算するために、これらの結果を使用する場合::
SELECT *
FROM words
WHERE song_id IN(337409,328981,304231)
ORDER BY song_id, global_position;
それは私がここにボンネットの下に何が起こっは考えているが、私は、適切なSQLオプティマイザは、私が上やった何だろうと想像
を完了するのに約30ミリ秒かかります。
私は以下を参照してください。出力説明を見て:
--UPDATE-- は(冗長、解析)説明入力されただけではなく、私がやる
"Merge Join (cost=20253.29..706336.00 rows=6312654 width=21) (actual time=240731.380..259453.350 rows=356 loops=1)"
" Output: words.song_id, words.word, words.global_position, words.line_number, words.verse_number"
" Merge Cond: (words.song_id = temp_song_id_with_all_stemmed_words.song_id)"
" CTE temp_song_id_with_all_stemmed_words"
" -> HashAggregate (cost=19799.62..19936.11 rows=13649 width=4) (actual time=43.168..44.916 rows=3 loops=1)"
" Output: stemmed_words.song_id"
" Group Key: stemmed_words.song_id"
" Filter: (count(*) = 5)"
" Rows Removed by Filter: 17181"
" -> Bitmap Heap Scan on public.stemmed_words (cost=474.02..19714.55 rows=17014 width=4) (actual time=10.254..31.899 rows=21099 loops=1)"
" Output: stemmed_words.stemmed_word, stemmed_words.song_id"
" Recheck Cond: (stemmed_words.stemmed_word = ANY ('{yesterdai,troubl,seem,awai,believ}'::text[]))"
" Heap Blocks: exact=12239"
" -> Bitmap Index Scan on stemmed_words_pkey (cost=0.00..469.76 rows=17014 width=0) (actual time=6.052..6.052 rows=21099 loops=1)"
" Index Cond: (stemmed_words.stemmed_word = ANY ('{yesterdai,troubl,seem,awai,believ}'::text[]))"
" -> Index Scan using words_song_id_global_position_idx on public.words (cost=0.44..653025.11 rows=12625308 width=21) (actual time=0.117..257820.366 rows=7860598 loops=1)"
" Output: words.song_id, words.word, words.global_position, words.line_number, words.verse_number"
" -> Sort (cost=316.75..317.25 rows=200 width=4) (actual time=44.953..45.017 rows=274 loops=1)"
" Output: temp_song_id_with_all_stemmed_words.song_id"
" Sort Key: temp_song_id_with_all_stemmed_words.song_id"
" Sort Method: quicksort Memory: 25kB"
" -> HashAggregate (cost=307.10..309.10 rows=200 width=4) (actual time=44.928..44.929 rows=3 loops=1)"
" Output: temp_song_id_with_all_stemmed_words.song_id"
" Group Key: temp_song_id_with_all_stemmed_words.song_id"
" -> CTE Scan on temp_song_id_with_all_stemmed_words (cost=0.00..272.98 rows=13649 width=4) (actual time=43.171..44.921 rows=3 loops=1)"
" Output: temp_song_id_with_all_stemmed_words.song_id"
"Planning time: 0.481 ms"
"Execution time: 259454.102 ms"
正直なところを説明そこに起こっていることを理解していない...私に中国のように見えます。
私はこれを2つの別々のものに分割するのではなく、1つのクエリとして最適化できると感じています。
- なぜ現在の形式で完了するのに時間がかかりますか?
- 私は上記のように2つの別々のものにクエリを分割して最適化できますか?
EXPLAIN ANALYZEの結果を表示できますか? –
あなたの質問と、**両方の**ステートメントの実行計画は、** 'explain(analyze、verbose)' **を使用して生成してください。 [_Formatted_](http://stackoverflow.com/help/formatting)** text **お願い、[スクリーンショットなし](http://meta.stackoverflow.com/questions/285551/why-may-i-not -upload-images-of-code-on-so-ask-a-question/285557#285557) –
CTEが最適化フェンスであるため、Postgresは文全体を最適化するのではなく、内側と外側のクエリを個別に最適化します。 CTEを 'from temp_song_id_with_all_stemmed_words'の代わりに' from(select ...) 'に移動すると、おそらくピクチャが変更されます。 –