PostgreSQLのカりントを高速化する方法


写真゜ヌス


誰もが数える方法を知っおいたすが、誰もがすぐに数える方法を知っおいるわけではありたせん。 この蚘事では、PostgreSQLのカりント最適化方法を詳しく芋おいきたす。 行数のカりントを桁違いに高速化できるトリックがありたす。


真剣に問題に取り組む堎合、 countのいく぀かのオプションを匷調衚瀺する必芁がありたす 。各オプションには独自のメ゜ッドがありたす。 決定する必芁があるもの



特定の状況ごずに゜リュヌションを分析し、速床ずリ゜ヌス消費を比范したす。 䞀元化されたデヌタベヌスの状況を調べた埌、Citusを䜿甚しお、分散デヌタベヌスでのcountの䞊列実行を実蚌したす。


内容



DBの準備


テストでは、 pgbenchが初期化されるcountずいうデヌタベヌスを䜿甚したす。


[user@comp ~]$ pgbench -i count 

テストテヌブルを䜜成したす。


 --       CREATE TABLE items AS SELECT (random()*1000000)::integer AS n, md5(random()::text) AS s FROM generate_series(1,1000000); --        VACUUM ANALYZE; 

重耇しお数える


正確なカりント

したがっお、最初から始めたしょう。テヌブル党䜓たたは重耇郚分がある郚分の正確な行数-叀き良きcount(*)取埗するこずを怜蚎したす。 このコマンドのランタむムは、行数をカりントする他の方法の速床を評䟡するための基瀎を提䟛したす。


Pgbenchは、パフォヌマンス統蚈を繰り返し照䌚および収集するための䟿利なツヌルです。


 #     PostgreSQL 9.5.4 echo "SELECT count(*) FROM items;" | pgbench -d count -t 50 -P 1 -f - # average 84.915 ms # stddev 5.251 ms 

count(1) vs count(*)に関するメモ。 count(*)は珟圚の行のすべおの列の倀を凊理する必芁があるため、 count(1)速いず考えるかもしれたせん。 実際にはその逆です。 SELECT *構造ずは異なり、 count(*)内のアスタリスクcount(*)は䜕も意味したせん。 PostgreSQLは、匏count(*)を匕数なしのカりントの特殊なケヌスずしお扱いたす。 この匏をcount()圢匏で蚘述するのが正しいでしょう。 䞀方、 count(1)は1぀の匕数を取り、PostgreSQLはこの匕数1が実際にNULLでないこずを各行で確認する必芁がありたす。


count(1)を䜿甚した以前のテストでは、次の結果が生成されたした。


 # average 98.896 ms # stddev 7.280 ms 

いずれにせよ、 count(1)ずcount(*)どちらも定矩䞊䜎速です。 同時トランザクションの䞀貫性を確保するために、PostgreSQLはMultiversion Concurrency ControlMVCCを䜿甚したす。 これは、各トランザクションがテヌブル内の異なる行、さらに異なる行数を芋るこずができるこずを意味したす。 したがっお、DBMSがキャッシュに入れるこずができる行の数に察しお単䞀の正しい倀はありたせん。システムはすべおの行をスキャンしお、どの行が単䞀のトランザクションから芋えるかを蚈算する必芁がありたす。 正確なカりントの実行時間は、テヌブルのサむズの増加に比䟋しお増加したす。


 EXPLAIN SELECT count(*) FROM items; Aggregate (cost=20834.00..20834.01 rows=1 width=0) -> Seq Scan on items (cost=0.00..18334.00 rows=1000000 width=0) 

芁求コストの88のアカりントをスキャンしたす。 テヌブルのサむズを2倍にするず、 スキャンず集蚈のコストが比䟋しお増加し、ク゚リの実行時間が玄2倍になりたす 。


行数平均時間
100侇85ミリ秒
200侇161ミリ秒
400侇343ミリ秒

スピヌドアップする方法は 2぀のオプションがありたす掚定倀が必芁であるこずを決定するか、自分でキャッシュに行数を入れたす。 2番目のケヌスでは、各テヌブルの倀ず、 countをすばやく実行する各WHERE匏を個別に保存する必芁がありたす 。


itemsテヌブル党䜓のcount(*)倀を手動でキャッシュする䟋を芋おみたしょう。 次のトリガヌベヌスの゜リュヌションは、 A。Elein Mustainによっお提案された方法の適応です。 PostgreSQL MVCC゚ンゞンは、 itemsず行カりント倀を含むテヌブルずの間の䞀貫性を維持したす。


 BEGIN; CREATE TABLE row_counts ( relname text PRIMARY KEY, reltuples bigint ); --       INSERT INTO row_counts (relname, reltuples) VALUES ('items', (SELECT count(*) from items)); CREATE OR REPLACE FUNCTION adjust_count() RETURNS TRIGGER AS $$ DECLARE BEGIN IF TG_OP = 'INSERT' THEN EXECUTE 'UPDATE row_counts set reltuples=reltuples +1 where relname = ''' || TG_RELNAME || ''''; RETURN NEW; ELSIF TG_OP = 'DELETE' THEN EXECUTE 'UPDATE row_counts set reltuples=reltuples -1 where relname = ''' || TG_RELNAME || ''''; RETURN OLD; END IF; END; $$ LANGUAGE 'plpgsql'; CREATE TRIGGER items_count BEFORE INSERT OR DELETE ON items FOR EACH ROW EXECUTE PROCEDURE adjust_count(); COMMIT; 

この堎合のキャッシュ倀の読み取りず曎新の速床はテヌブルのサむズに䟝存せず、行数の倀の取埗は非垞に高速です。 ただし、この手法では、挿入および削陀操䜜のオヌバヌヘッドが増加したす。 トリガヌを䜿甚しない堎合、次のコマンドは4.7秒で実行されたすが、トリガヌを䜿甚した挿入では50倍遅くなりたす 。


 INSERT INTO items (n, s) SELECT (random()*1000000)::integer AS n, md5(random()::text) AS s FROM generate_series(1,1000000); 

栌付け

テヌブル党䜓のスコア

テヌブル内の行数をキャッシュするアプロヌチにより、貌り付け操䜜が遅くなりたす。 正確な数ではなく、掚定倀に満足する準備ができおいる堎合、挿入時間に圱響を䞎えずに高速の読み取り操䜜を取埗できたす。 このために、PostgreSQLによっお収集されたオヌバヌヘッドを䜿甚できたす。 それらの゜ヌスは、 統蚈情報コレクタず自動バキュヌムデヌモンです。


掚定倀を取埗するためのオプション


 --   "stats collector" SELECT n_live_tup FROM pg_stat_all_tables WHERE relname = 'items'; --  VACUUM  ANALYZE SELECT reltuples FROM pg_class WHERE relname = 'items'; 

しかし、より信頌性の高い゜ヌスがあり、そのデヌタはより頻繁に曎新されたす。 Andrew GierthRhodiumToadのアドバむス


芚えおおいおくださいスケゞュヌラは実際にはreltuplesを䜿甚したせん; reltuples / relpages比に珟圚のペヌゞ数を掛けたす。

ここでのロゞックは次のずおりです。テヌブル内のデヌタ量が増加しおも、物理ペヌゞに収たる行の平均数は通垞、合蚈数ほど倉化したせん。 珟圚の行数のより正確な掚定倀を取埗するために、平均行数に、テヌブルが占有しおいる珟圚のペヌゞ数に関する珟圚の情報を掛けるこずができたす。


 -- pg_relation_size  block_size   , --        --      SELECT (reltuples/relpages) * ( pg_relation_size('items') / (current_setting('block_size')::integer) ) FROM pg_class where relname = 'items'; 

サンプルのスコア

前のセクションでは、テヌブル党䜓の掚定行数を取埗するこずを怜蚎したしたが、同じこずは可胜ですが、 WHERE䞀臎する行に察しおのみ可胜ですか Michael Fuhrは興味深い方法を思い぀きたした。ク゚リに察しおEXPLAINを実行し、結果を分析したす。


 CREATE FUNCTION count_estimate(query text) RETURNS integer AS $$ DECLARE rec record; rows integer; BEGIN FOR rec IN EXECUTE 'EXPLAIN ' || query LOOP rows := substring(rec."QUERY PLAN" FROM ' rows=([[:digit:]]+)'); EXIT WHEN rows IS NOT NULL; END LOOP; RETURN rows; END; $$ LANGUAGE plpgsql VOLATILE STRICT; 

この関数は次のように䜿甚できたす。


 SELECT count_estimate('SELECT 1 FROM items WHERE n < 1000'); 

このメ゜ッドの粟床は、 WHERE遞択性を評䟡するためにさたざたなメ゜ッドを䜿甚するスケゞュヌラヌず、ク゚リから返される行数を取埗できる堎所に䟝存したす。


明確なカりント重耇なし


正確なカりント

メモリ䞍足のデフォルト動䜜

重耇したカりントはゆっくり実行される堎合がありたすが、個別カりントの方がはるかに悪いです。 限られた䜜業メモリずむンデックスなしでは、PostgreSQLは最適化を効率的に実行できたせん。 デフォルト構成では、DBMSは各䞊列リク゚スト work_mem にハヌド制限を課したす。 開発に䜿甚するコンピュヌタヌでは、このデフォルト倀は4メガバむトに蚭定されおいたした。


work_mem工堎蚭定で100䞇行を凊理するパフォヌマンスを評䟡したしょう。


 echo "SELECT count(DISTINCT n) FROM items;" | pgbench -d count -t 50 -P 1 -f - # average 742.855 ms # stddev 21.907 ms echo "SELECT count(DISTINCT s) FROM items;" | pgbench -d count -t 5 -P 1 -f - # average 31747.337 ms # stddev 267.183 ms 

EXPLAINを実行するず、ク゚リの実行時間のほずんどが集玄に費やされたこずがわかりたす。 たた、 テキストタむプの列の行数をカりントするこずは、敎数よりもはるかに遅いこずに泚意しおください。





 --     "integer", n Aggregate (cost=20834.00..20834.01 rows=1 width=4) (actual time=860.620..860.620 rows=1 loops=1) Output: count(DISTINCT n) Buffers: shared hit=3904 read=4430, temp read=1467 written=1467 -> Seq Scan on public.items (cost=0.00..18334.00 rows=1000000 width=4) (actual time=0.005..107.702 rows=1000000 loops=1) Output: n, s Buffers: shared hit=3904 read=4430 --     "text", s Aggregate (cost=20834.00..20834.01 rows=1 width=33) (actual time=31172.340..31172.340 rows=1 loops=1) Output: count(DISTINCT s) Buffers: shared hit=3936 read=4398, temp read=5111 written=5111 -> Seq Scan on public.items (cost=0.00..18334.00 rows=1000000 width=33) (actual time=0.005..142.276 rows=1000000 loops=1) Output: n, s Buffers: shared hit=3936 read=4398 

「集合䜓」の内郚で䜕が起こりたすか EXPLAIN出力のこのプロシヌゞャの説明は䞍透明です。 同様のク゚リの分析は、状況を理解するのに圹立ちたす。 count distinctをselect distinct眮き換えcount distinct 。





 EXPLAIN (ANALYZE, VERBOSE) SELECT DISTINCT n FROM items; Unique (cost=131666.34..136666.34 rows=498824 width=4) (actual time=766.775..1229.040 rows=631846 loops=1) Output: n -> Sort (cost=131666.34..134166.34 rows=1000000 width=4) (actual time=766.774..1075.712 rows=1000000 loops=1) Output: n Sort Key: items.n Sort Method: external merge Disk: 13632kB -> Seq Scan on public.items (cost=0.00..18334.00 rows=1000000 width=4) (actual time=0.006..178.153 rows=1000000 loops=1) Output: n 

work_memが䞍十分で、倖郚デヌタ構造むンデックスなどが存圚しない状況では、PostgreSQLはメモリずディスク間でマヌゞ゜ヌトテヌブルを実行し 、結果を反埩しお重耇を削陀しsort | uniq sort | uniq


特に敎数列nではなく、文字列sを䜿甚する堎合、゜ヌトはク゚リの実行時間の倧郚分を占めたす。 䞡方の堎合の重耇䞀意のフィルタヌの削陀は、ほが同じ速床で実行されたす。


特殊な集玄

䞀意の倀の数をカりントするために、Thomas Vondraは、長さが制限されたタむプ64ビットを超えおはならないで機胜する特殊な集玄メ゜ッドを䜜成したした。 この方法は、䜜業メモリを増やしたりむンデックスを䜜成したりしなくおも、デフォルトの゜ヌトベヌスの方法よりも高速です。 次の手順に埓っおむンストヌルしたす。


  1. tvondra / count_distinctプロゞェクトのコピヌを䜜成したす。
  2. 安定したブランチに切り替えたす git checkout REL2_0_STABLE 。
  3. make install実行したす。
  4. デヌタベヌスで、 CREATE EXTENSION. count_distinct;実行したすCREATE EXTENSION. count_distinct; CREATE EXTENSION. count_distinct; 。

この蚘事では、 Thomasが集蚈の仕組みに぀いお説明しおいたす。 圌のメ゜ッドはメモリ内に䞀意の芁玠の゜ヌトされた配列を䜜成し、プロセスでそれを圧瞮するず簡単に蚀いたす。


 echo "SELECT COUNT_DISTINCT(n) FROM items;" | pgbench -d count -t 50 -P 1 -f - # average 434.726 ms # stddev 19.955 ms 

これは、テストデヌタで平均742ミリ秒で実行される暙準カりントdistinctよりも速く動䜜したす。 count_distinctなど、Cで蚘述された拡匵機胜はwork_memパラメヌタヌに限定されないため、プロセスで䜜成された配列は、圓初蚈画したよりも倚くのメモリを接続ごずに䜿甚する可胜性があるこずに泚意しおください。


ハッシュ集蚈

再蚈算されたすべおの列がwork_memに収たる堎合、PostgreSQLはハッシュテヌブルを䜿甚しお䞀意の倀を取埗したす。





 SET work_mem='1GB'; EXPLAIN SELECT DISTINCT n FROM items; HashAggregate (cost=20834.00..25822.24 rows=498824 width=4) Group Key: n -> Seq Scan on items (cost=0.00..18334.00 rows=1000000 width=4) 

これは、調査した方法の䞭で最速です。 nで平均372ミリ秒、 s 23秒で実行されたす。 select distinct n select count(distinct n)をselect count(distinct n)ず、ハッシュの集蚈もHashAggregateに適甚されるこずを条件に、 select count(distinct n) select distinct nおよびselect count(distinct n)ク゚リはほが同じ時間動䜜したす。


泚意 work_memは各䞊列リク゚ストを参照するため、䜜業メモリに高い制限を蚭定するず、䞍快な結果を招く可胜性がありたす。 さらに、より良いものを思い぀くこずができたす。


むンデックスのみのスキャン

この機胜はPostgreSQL 9.2で登堎したした。 むンデックスにク゚リに必芁なすべおのデヌタが含たれおいる堎合、システムはテヌブル自䜓「ヒヌプ」に觊れるこずなく、むンデックスのみを䜿甚できたす。 むンデックスタむプはむンデックスのみのスキャンをサポヌトする必芁がありたす 䟋 btree 。 GiSTおよびSP-GiSTむンデックスは、特定のクラスの挔算子に察しおのみむンデックスのみのスキャンをサポヌトしたす 。


列nおよびs btreeむンデックスを䜜成したす。


 CREATE INDEX items_n_idx ON items USING btree (n); CREATE INDEX items_s_idx ON items USING btree (s); 

これらの列から䞀意の倀を遞択するために、別の戊略が䜿甚されるようになりたした。





 EXPLAIN SELECT DISTINCT n FROM items; Unique (cost=0.42..28480.42 rows=491891 width=4) -> Index Only Scan using items_n_idx on items (cost=0.42..25980.42 rows=1000000 width=4) 

しかし、ここで奇劙な問題に遭遇しSELECT COUNT(DISTINCT n) FROM itemsは、 SELECT DISTINCT nがデフォルトでこれを行うにもかかわらず、むンデックスを䜿甚したせん。 ブログのヒント 「postgresを50倍高速化するトリック」 に埓うこずで、サブク゚リのcountずはcount distinct countを曞き換えるこずにより、スケゞュヌラヌにヒントを䞎えるこずができたす。


 -- SELECT COUNT(DISTINCT n) FROM items; --      EXPLAIN SELECT COUNT(*) FROM (SELECT DISTINCT n FROM items) t; Aggregate (cost=34629.06..34629.07 rows=1 width=0) -> Unique (cost=0.42..28480.42 rows=491891 width=4) -> Index Only Scan using items_n_idx on items (cost=0.42..25980.42 rows=1000000 width=4) 

順序察称の二分朚探玢は高速です。 このク゚リの平均所芁時間は177ミリ秒列s 270ミリ秒です。


備考 work_memの倀がテヌブル党䜓をホストするのに十分な堎合、PostgreSQLはむンデックスが存圚する堎合でもHashAggregateを遞択したす。 これは逆説です。システムにより倚くのメモリを割り圓おるず、最悪のク゚リプランが遞択されるこずになりたす。 SET enable_hashagg=false;蚭定するこずにより、 むンデックスのみのスキャンの遞択を匷制するこずができSET enable_hashagg=false; 、他のリク゚ストの蚈画を損なわないように、 trueに戻すこずを忘れないでください。


栌付け

HyperLogLog

以前に怜蚎された方法は、むンデックス、ハッシュテヌブル、メモリ内の゜ヌトされた配列、たたは集䞭型デヌタベヌスの統蚈テヌブルぞのアクセスに䟝存したす。 本圓に倧量のデヌタがある堎合、および/たたはそれらが分散デヌタベヌスの耇数のノヌド間で共有される堎合、これらの方法は私たちに適さなくなりたす。


この堎合、確率的デヌタ構造が助けになりたす。これは、倧たかな芋積もりをすばやく行うこずができ、十分に䞊列化されおいたす。 count distinctでこれらの構造の1぀を詊しおみたしょう。 HyperLogLogHLLず呌ばれるカヌディナリティヌ掚定量を怜蚎しおください。 䞀連の芁玠を衚すために少量のメモリを䜿甚したす。 このメカニズムの和集合挔算は損倱なしで機胜するため、数量掚定の粟床を損なうこずなく任意のHLL倀を組み合わせるこずができたす。


HLLは、「良い」ハッシュ関数のプロパティ、特にハッシュ倀間の距離を䜿甚したす。 倀を均等に分垃させる関数は、倀を可胜な限り広げる傟向がありたす。 新しいハッシュが远加されるず、空き領域が小さくなり、芁玠が互いにくっ぀き始めたす。 ハッシュ倀間の最小距離を分析するこずにより、アルゎリズムは゜ヌス芁玠の最も可胜性の高い数を掚定できたす。


速床を枬定したしょう。 たず、PostgreSQLの拡匵機胜をむンストヌルしたす。


  1. postgresql-hllプロゞェクトのコピヌを䜜成したす。
  2. make install実行したす。
  3. デヌタベヌスにhll拡匵機胜を䜜成したす。CREATE CREATE EXTENSION hll; 。

HLLは、テヌブルの順次スキャン順次スキャン䞭に高速デヌタ集玄を実行したす。


 EXPLAIN SELECT #hll_add_agg(hll_hash_integer(n)) FROM items; Aggregate (cost=23334.00..23334.01 rows=1 width=4) -> Seq Scan on items (cost=0.00..18334.00 rows=1000000 width=4) 

count distinct実行するずきの平均HLL速床は、列n 239ミリ秒、 s 284ミリ秒でした。 100䞇件のレコヌドのむンデックスのみのスキャンよりも少し遅くなりたした。 HLLの真の匷さは、損倱なしに行われる連想および可換の和集合挔算により明らかになりたす。 これは、それらを䞊行しお実行し、組み合わせお最終結果を蚈算できるこずを意味したす。


䞊列化


Googleアナリティクスなどのリアルタむム分析を収集するアプリケヌションは、 countを積極的に䜿甚し、この操䜜は十分に䞊列化されおいたす。 このセクションでは、 Citus Cloudにデプロむされた小さなCitusクラスタヌに基づいお、いく぀かの行カりント方法のパフォヌマンスを枬定したす。


アむデアは、分散デヌタベヌスノヌドを耇数のマシンに展開するこずです。 ノヌドは同じスキヌムを持ち、各ノヌドには䞀般的なデヌタセットシャヌドの䞀郚が含たれたす。 行数のカりントは、䞊行しお、぀たり異なるマシンで同時に実行されたす。


クラスタヌのセットアップ

私たちの目暙は比范パフォヌマンスを評䟡するこずであり、最倧速床を取埗しないため、テストでは小さなクラスタヌのみを䜜成したす。


Citus Cloudでは、8台のマシンのクラスタヌを䜜成し、各マシンに可胜な限り匱い構成を遞択したした。 この䟋を再珟したい堎合は、 ここに登録しおください 。


クラスタヌを䜜成した埌、調敎ノヌドに接続しおSQLク゚リを実行したす。 たず、テヌブルを䜜成したす。


 CREATE TABLE items ( n integer, s text ); 

珟時点では、テヌブルはコヌディネヌタヌデヌタベヌスにのみ存圚したす。 テヌブルを分割し、その郚分を䜜業ノヌドに配眮する必芁がありたす。 Citusは、遞択された分垃列分垃列の倀を凊理するこずにより、特定のセグメント断片に各行を割り圓おたす。 次の䟋では、 itemsテヌブルの将来の行を分散するタスクを蚭定したすn列の倀のハッシュを䜿甚しお、特定のセグメントに属するかどうかを刀断したす。


 SELECT master_create_distributed_table('items', 'n', 'hash'); SELECT master_create_worker_shards('items', 32, 1); 

調敎ノヌドを䜿甚しお、ランダムデヌタをデヌタベヌスセグメントにロヌドしたす。 Citusは、デヌタをすばやくロヌドするために䜿甚されるMX マスタヌレスモヌドもサポヌトしおいたすが、珟圚は興味がありたせん。


クラスタヌコヌディネヌタヌデヌタベヌスのURLを受信した埌、高速ネットワヌク接続のコンピュヌタヌで次のコヌドを実行したす。 生成されたデヌタはすべおこのマシンからネットワヌクを介しお送信されるため、十分な速床が必芁です。


 cat << EOF > randgen.sql COPY ( SELECT (random()*100000000)::integer AS n, md5(random()::text) AS s FROM generate_series(1,100000000) ) TO STDOUT; EOF psql $CITUS_URL -q -f randgen.sql | \ psql $CITUS_URL -c "COPY items (n, s) FROM STDIN" 

集䞭デヌタベヌスの䟋では、100䞇行を䜿甚したした。 今回は、1億を取りたしょう。


正確なカりント

重耇あり

通垞のカりント 重耇なしは問題を匕き起こしたせん。 コヌディネヌタヌは、すべおのノヌドでク゚リを実行し、結果を芁玄したす。 EXPLAIN出力には、䜜業ノヌドの1぀で遞択されたプラン「分散ク゚リ」ずコヌディネヌタヌで遞択されたプラン「マスタヌク゚リ」が衚瀺されたす。


 EXPLAIN VERBOSE SELECT count(*) FROM items; Distributed Query into pg_merge_job_0003 Executor: Real-Time Task Count: 32 Tasks Shown: One of 32 -> Task Node: host=*** port=5432 dbname=citus -> Aggregate (cost=65159.34..65159.35 rows=1 width=0) Output: count(*) -> Seq Scan on public.items_102009 items (cost=0.00..57340.27 rows=3127627 width=0) Output: n, s Master Query -> Aggregate (cost=0.00..0.02 rows=1 width=0) Output: (sum(intermediate_column_3_0))::bigint -> Seq Scan on pg_temp_2.pg_merge_job_0003 (cost=0.00..0.00 rows=0 width=0) Output: intermediate_column_3_0 

参照甚クラスタヌでは、このリク゚ストは1.2秒実行されたす。 分散デヌタベヌスを䜿甚する堎合、 個別のカりントはより深刻な問題を匕き起こしたす。


個別重耇なし

分散デヌタベヌスで䞀意の列倀を蚈算するこずの難しさは、異なるノヌドで重耇を探す必芁があるこずです。 ただし、分垃列の倀を読み取る堎合、これは問題です。 この列に同じ倀を持぀行は1぀のセグメントに分類され、セグメント間の重耇を防ぎたす。


Citusは、分垃列の䞀意の倀をカりントするには、各ノヌドでcount distinctのcount distinctク゚リを実行し、結果を远加する必芁があるこずを知っおいたす。 クラスタヌはこのタスクを3.4秒で実行したす。


通垞の列非分垃で䞀意の倀の数を芋぀けるこずはより困難です。 論理的には、2぀の可胜性がありたす。


  1. すべおの行を調敎ノヌドにコピヌし、そこでカりントしたす。
  2. , , , , .

. .


«» (repartitioning). , , , . , . . Citus , .



, HLL, . (non-distribution), . HLL . HLL , , .


Citus postgresql-hll. citus.count_distinct_error_rate , Citus count distinct HLL. 䟋


 SET citus.count_distinct_error_rate = 0.005; EXPLAIN VERBOSE SELECT count(DISTINCT n) FROM items; Distributed Query into pg_merge_job_0090 Executor: Real-Time Task Count: 32 Tasks Shown: One of 32 -> Task Node: host=*** port=5432 dbname=citus -> Aggregate (cost=72978.41..72978.42 rows=1 width=4) Output: hll_add_agg(hll_hash_integer(n, 0), 15) -> Seq Scan on public.items_102009 items (cost=0.00..57340.27 rows=3127627 width=4) Output: n, s Master Query -> Aggregate (cost=0.00..0.02 rows=1 width=0) Output: (hll_cardinality(hll_union_agg(intermediate_column_90_0)))::bigint -> Seq Scan on pg_temp_2.pg_merge_job_0090 (cost=0.00..0.00 rows=0 width=0) Output: intermediate_column_90_0 

: 3,2 n 3,8 s . 100 (non-distribution) ! HLL — .


たずめ


方法/1
PG Stats0,3---
EXPLAIN0,3-+-
2 ( )+--
count(*)85++-
count(1)99++-
Index Only Scan177+++
HLL239-++
HashAgg372+++
Custom Agg435 ( 64-bit)+++
Mergesort742+++

index-only scan , HyperLogLog (HLL) (> 100 ). , (distinct count) .



Source: https://habr.com/ru/post/J316304/


All Articles