8.4より前のPostgreSQL向けに作成された古いコードをレビューしたところ、本当に気の利いたものが見つかりました。当時はカスタム関数でこれの一部を実行していたことを覚えていますが、事前にarray_agg()
どのようなものかを忘れていました。レビューのために、現代の集計はこのように書かれています。
SELECT array_agg(x ORDER BY x DESC) FROM foobar;
しかし、昔々、このように書かれていました、
SELECT ARRAY(SELECT x FROM foobar ORDER BY x DESC);
それで、私はいくつかのテストデータでそれを試しました。
CREATE TEMP TABLE foobar AS
SELECT * FROM generate_series(1,1e7)
AS t(x);
結果は驚くべきものでした。.#OldSchoolCoolの方法は非常に高速で、25%高速化されました。さらに、ORDERを使用せずに単純化すると、同じ遅延が示されました。
# EXPLAIN ANALYZE SELECT ARRAY(SELECT x FROM foobar);
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------
Result (cost=104425.28..104425.29 rows=1 width=0) (actual time=1665.948..1665.949 rows=1 loops=1)
InitPlan 1 (returns $0)
-> Seq Scan on foobar (cost=0.00..104425.28 rows=6017728 width=32) (actual time=0.032..716.793 rows=10000000 loops=1)
Planning time: 0.068 ms
Execution time: 1671.482 ms
(5 rows)
test=# EXPLAIN ANALYZE SELECT array_agg(x) FROM foobar;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------
Aggregate (cost=119469.60..119469.61 rows=1 width=32) (actual time=2155.154..2155.154 rows=1 loops=1)
-> Seq Scan on foobar (cost=0.00..104425.28 rows=6017728 width=32) (actual time=0.031..717.831 rows=10000000 loops=1)
Planning time: 0.054 ms
Execution time: 2174.753 ms
(4 rows)
それで、ここで何が起こっているのか。内部関数であるarray_aggが、プランナーのSQLブードゥー教よりもずっと遅いのはなぜですか?
「gcc(Ubuntu 6.2.0-5ubuntu12)6.2.0 20161005、64ビットでコンパイルされたx86_64-pc-linux-gnuでのPostgreSQL 9.5.5の使用」
array_agg
ARRAY
コンストラクターがUNION
内部的に式としてa とほぼ同等の処理をしているように見える入力の順序を追跡する必要があります。推測array_agg
する必要がある場合は、おそらくより多くのメモリが必要になります。これを徹底的にテストすることはできませんでしたが、Ubuntu 16.04で実行されているPostgreSQL 9.6では、ARRAY()
クエリORDER BY
は外部マージを使用し、array_agg
クエリよりも低速でした。あなたが言ったように、コードを読むことを除いて、あなたの答えは私たちが持っている最高の説明です。