SlideShare a Scribd company logo
© 2023 NTT DATA Corporation
© 2023 NTT DATA Corporation
NewSQL/分散SQLデータベース よろず勉強会 #3
YugabyteDBの実行計画を眺める
2023年2月16日
NTTデータ 笠原辰仁
© 2023 NTT DATA Corporation 2
自己紹介
• 笠原 辰仁 (@kasa_zip)
• 長年PostgreSQLの検証や周辺ツールの開発、サポートなどに従事
• 最近はNewSQLや分散データベースに属するOSSプロダクトの調査や検証、
適用領域の見極めなど
• 本日は、分散データベースのOSSプロダクトであるYugabyteDBの実行計画の取得方法や
情報の見方を解説
© 2023 NTT DATA Corporation 3
実行計画とは
発行されたクエリをどのように実行するかをDBMSが生成する情報。一般的にはDBMSのPlannerやOptimizerと呼ばれる機能
が生成する。
通常、あまりユーザ(クエリを発行する人)が実行計画を意識することは無いが、思ったような性能が出ない場合の原因解析やクエ
リチューニングを行った効果などを調査したい時に、とても有用なもの。
SELECT * FROM t1 JOIN t2 ON t1.c1 = t2.c1 WHERE t1.c1 < 10;
QUERY PLAN
--------------------------------------
Nested Loop
Join Filter: (t1.c1 = t2.c1)
-> Index Scan using t1_pkey on t1
Index Cond: (c1 < 10)
-> Seq Scan on t2
YugabyteDB
(のPlanner)
© 2023 NTT DATA Corporation 4
実行計画の取得方法
YugabyteDBでは他のDBMSと同様にEXPLAINという句をクエリの先頭に付与することで実行計画を取得できる。
クエリは実際には実行されない。出力される情報はPostgreSQLとほぼ同じ。
yugabyte=# EXPLAIN SELECT * FROM r_t1 WHERE c1 < 100;
QUERY PLAN
-----------------------------------------------------------------------
Index Scan using r_t1_pkey on r_t1 (cost=0.00..4.11 rows=1 width=52)
Index Cond: (c1 < 100)
(2 rows)
yugabyte=# EXPLAIN SELECT * FROM r_t1;
QUERY PLAN
----------------------------------------------------------
Seq Scan on r_t1 (cost=0.00..100.00 rows=1000 width=52)
(1 row)
yugabyte=# EXPLAIN SELECT * FROM r_t1 r JOIN h_t1 h ON r.c1 = h.c1 WHERE r.c1 < 100;
QUERY PLAN
-------------------------------------------------------------------------------
Nested Loop (cost=0.00..8.23 rows=1 width=104)
-> Index Scan using r_t1_pkey on r_t1 r (cost=0.00..4.11 rows=1 width=52)
Index Cond: (c1 < 100)
-> Index Scan using h_t1_pkey on h_t1 h (cost=0.00..4.11 rows=1 width=52)
Index Cond: (c1 = r.c1)
(5 rows)
© 2023 NTT DATA Corporation 5
実行計画の取得方法
EXPLAINではオプションをいくつか付与することで様々な情報を出力できる。
オプション 説明
ANALYZE 指定したクエリを実行し、実際の所要時間や消費した各種リソース(IOやメモリなど)の情報を出力する。
VERBOSE SELECT列の射影対象や中間処理での出力対象を出力する。
COSTS 実行計画のコスト情報を出力する。デフォルト有効。
TIMING 実行時の所要時間を出力する。ANALYZEの指定が必須でデフォルト有効。
BUFFERS 実行過程における巨大なハッシュやソート処理の一時ファイル書き出しで使用されたバッファサイズを出力す
る。ANALYZEの指定が必須。
SUMMARY 実行計画の末尾にプラン作成時間、実行時間、総メモリ消費量などを出力する。デフォルト有効。
FORMAT 実行計画情報の出力形式を指定する。TEXT、JSON、YAML、XMLから選択できデフォルトはTEXT。
DIST ストレージ層のDocDBへの読み書きリクエスト数やDocDBでの所要時間を出力する。
ANALYZEオプションを付与することで実際の所要時間が分かるため多用することが多い。ただし実際にクエリが実行されるため更
新系の処理を対象にするときは注意。(BEGIN; ABORT;で囲うなど工夫がいる)
COSTSやTIMING、SUMMARYについては変動要素の強い出力情報になるので、リグレッションテストなどの出力と期待のdiff
を取るときなどのノイズ除去として用いられたり、実行計画を簡潔に出力したい場合などに用いる。
© 2023 NTT DATA Corporation 6
EXPLAINの文法
EXPLAINでは複数のオプションを組み合わせて使用できる。以下のようにEXPLAIN (オプション [,..]) の形で指定する。
EXPLAIN (ANALYZE, BUFFERS, VERBOSE) SELECT …
上記はANALYZE、BUFFERS、VERBOSEを有効にしている。オプション [on | off] の形を取ることもできる。
EXPLAIN (ANALYZE on, BUFFERS on, COSTS off) SELECT …
上記はANALYZE、BUFFERSを有効にし、COSTSを無効にしている。
EXPLAINは通常のSELECTやUPDATEなどのクエリの他、カーソルのDECLARE、準備文(Prepared Statement)に対する
EXECUTEにも使用することができる。
PREPARE p1(int) AS SELECT … WHERE c1 = $1;
EXPLAIN (ANALYZE on, BUFFERS on) EXECUTE p1(10);
EXPLAIN (ANALYZE on, BUFFERS on) DECLARE cur FOR SELECT …
© 2023 NTT DATA Corporation 7
実行計画の見方
=> EXPLAIN SELECT * FROM r_t1 r JOIN h_t1 h ON r.c1 = h.c1 WHERE h.c1 < 10;
QUERY PLAN
-------------------------------------------------------------------------------
Nested Loop (cost=0.00..216.39 rows=1000 width=104)
-> Seq Scan on h_t1 h (cost=0.00..102.50 rows=1000 width=52)
Filter: (c1 < 10)
-> Index Scan using r_t1_pkey on r_t1 r (cost=0.00..0.11 rows=1 width=52)
Index Cond: (c1 = h.c1)
(5 rows)
赤字部分はノードタイプとも呼ばれ、実行されるスキャン、
結合、集計等の各処理の種別を表す。
基本的にネストの深い方(右の方)から順次実行されていく
代表的なノードタイプには以下がある。
• スキャン:Seq Scan/Index Scan/Index Only Scan
• 結合:Nested Loop/Merge Join/Hash Join (Semi/Anti)
• 集計:HashAggregate/GroupAggregate
• 更新:Insert/Update/Delete
• その他:Sort/Limit/Result/Append… など。
ちなみにPostgreSQLにあるBitmapScanは無い
まず計画そのものとなるノード情報。
© 2023 NTT DATA Corporation 8
実行計画の見方
=> EXPLAIN SELECT * FROM r_t1 r JOIN h_t1 h ON r.c1 = h.c1 WHERE h.c1 < 10;
QUERY PLAN
-------------------------------------------------------------------------------
Nested Loop (cost=0.00..216.39 rows=1000 width=104)
-> Seq Scan on h_t1 h (cost=0.00..102.50 rows=1000 width=52)
Filter: (c1 < 10)
-> Index Scan using r_t1_pkey on r_t1 r (cost=0.00..0.11 rows=1 width=52)
Index Cond: (c1 = h.c1)
(5 rows)
赤字部分はコストに関する情報で、N.NN .. M.MMはそれぞれ
スタートアップコスト(そのノードを開始するための準備コスト)と
トータルコスト(ノード処理を一通り完了するまでの総コスト)。
rowsは各ノードで取得する予想行数。
widthは各ノードで取得する列幅の総サイズ。
コストの計算式はPostgreSQLと同様のロジックだが、
YugabyteDB特有の要素がいくつかある。(異なるゾーン
やリージョンへの問い合わせコストは別途追加するなど)
src/backend/access/yb_access/yb_scan.cの
ybcCostEstimate()
Plannerが実行計画の作成の根拠とした見積情報。
© 2023 NTT DATA Corporation 9
実行計画の見方
=> EXPLAIN (ANALYZE on, COSTS off) SELECT r.c1, r.c4 FROM r_t1 r JOIN h_t1 h ON r.c1 = h.c1 WHERE h.c1 < 100;
QUERY PLAN
---------------------------------------------------------------------------------------
Nested Loop (actual time=12.706..1979.256 rows=99 loops=1)
-> Seq Scan on h_t1 h (actual time=7.545..1669.513 rows=99 loops=1)
Filter: (c1 < 100)
Rows Removed by Filter: 599901
-> Index Scan using r_t1_pkey on r_t1 r (actual time=3.108..3.108 rows=1 loops=99)
Index Cond: (c1 = h.c1)
Planning Time: 0.127 ms
Execution Time: 1979.423 ms
Peak Memory Usage: 30 kB
(9 rows)
赤字部分は実際にかかった時間や取得した行数情報。
actual timeのNN.NN .. MM.MMは各ノードで最初の1行を取得す
るまでの時間(ms)と最後の行を取得するまでの時間(ms)。
rowsは各ノードで取得された件数。
loopsは各ノードが繰り返された回数。
Rows Removed by Filterはスキャンした件数のうち条件により除去
された件数。
loopsが2以上の場合、実際にかかる時間は
「actual time」 * 「loops回数」となる。
loopsが多いものはactual timeが短くても注意すると良い。
実際にクエリを実行した場合の所要時間や取得した件数などの情報。
© 2023 NTT DATA Corporation 10
実行計画の見方
=> EXPLAIN (ANALYZE on, COSTS off) SELECT r.c1, r.c4 FROM r_t1 r JOIN h_t1 h ON r.c1 = h.c1 WHERE h.c1 < 100;
QUERY PLAN
---------------------------------------------------------------------------------------
Nested Loop (actual time=12.706..1979.256 rows=99 loops=1)
-> Seq Scan on h_t1 h (actual time=7.545..1669.513 rows=99 loops=1)
Filter: (c1 < 100)
Rows Removed by Filter: 599901
-> Index Scan using r_t1_pkey on r_t1 r (actual time=3.108..3.108 rows=1 loops=99)
Index Cond: (c1 = h.c1)
Planning Time: 0.127 ms
Execution Time: 1979.423 ms
Peak Memory Usage: 30 kB
(9 rows)
赤字部分はサマリ情報。
Planning Timeはプラン作成にかかった時間。
Execution Timeはクエリ処理にかかった総時間。
Peak Memory Usageはクエリ処理中の最もメモリを消費していた際
の利用量(Tserver上のpostgresバックエンドでの消費量)。
Execution TimeはYugabyteDB内での所要時間となり、
クライアントへ結果を返すなどの通信時間などは含まれない
ので注意。
実際にクエリを実行した場合のサマリ情報。
© 2023 NTT DATA Corporation 11
実行計画の見方
=> EXPLAIN (ANALYZE on, DIST on, COSTS off) SELECT r.c1, r.c4 FROM r_t1 r JOIN h_t1 h ON r.c1 = h.c1 WHERE h.c1 < 100;
QUERY PLAN
---------------------------------------------------------------------------------------
Nested Loop (actual time=20.376..1765.325 rows=99 loops=1)
-> Seq Scan on h_t1 h (actual time=6.409..1478.253 rows=99 loops=1)
Filter: (c1 < 100)
Rows Removed by Filter: 599901
Storage Table Read Requests: 588
Storage Table Execution Time: 1424.985 ms
-> Index Scan using r_t1_pkey on r_t1 r (actual time=2.882..2.882 rows=1 loops=99)
Index Cond: (c1 = h.c1)
Storage Index Read Requests: 1
Storage Index Execution Time: 2.859 ms
Planning Time: 0.085 ms
Execution Time: 1765.460 ms
Storage Read Requests: 687
Storage Write Requests: 0
Storage Execution Time: 1707.983 ms
Peak Memory Usage: 30 kB
(16 rows)
赤字部分はストレージ(DocDB)での処理時間や回数の情報。
Storage Table~はSeqScan処理でDocDBへ行われたRPCの回数と所要時間。
Storage Index~はIndex Scan処理でDocDBへ行われたRPCの回数と所要時
間。
Storage Read/Write RequestはDocDBへリクエストされたRPCの総回数。
Storage Execution TimeはDocDBでの処理総時間。
なお、loopsが2以上の場合はStorage~Requestsはその回数だけ実施される。
DISTオプションによる実際にクエリを実行した場合のDocDBでの処理時間やリクエスト回数などの情報。
© 2023 NTT DATA Corporation 12
YugabyteDBのユニークな処理 – HashとRange -
YugabyteDBではインデックスはデフォルトでハッシュインデックスが利用される。そのため範囲検索を多用する場合はインデックス
定義に注意しておく。
=# CREATE TABLE r_t1 (c1 int, c2 int, c3 int, c4 text, c5 timestamp, primary key (c1 ASC)); -- 主キーはRange
=# CREATE TABLE h_t1 (c1 int, c2 int, c3 int, c4 text, c5 timestamp, primary key (c1)); -- 主キーはHash
(各テーブルに60万件ほど投入)
=# EXPLAIN (ANALYZE on, COSTS off) SELECT * FROM r_t1 WHERE c1 < 100;
QUERY PLAN
-------------------------------------------------------------------------------
Index Scan using r_t1_pkey on r_t1 (actual time=1.099..1.134 rows=99 loops=1)
Index Cond: (c1 < 100)
Planning Time: 0.055 ms
Execution Time: 1.163 ms
Peak Memory Usage: 0 kB
(5 rows)
=# EXPLAIN (ANALYZE on, COSTS off) SELECT * FROM h_t1 WHERE c1 < 100;
QUERY PLAN
-----------------------------------------------------------------
Seq Scan on h_t1 (actual time=19.090..2783.098 rows=99 loops=1)
Filter: (c1 < 100)
Rows Removed by Filter: 599901
Planning Time: 1.557 ms
Execution Time: 2783.488 ms
Peak Memory Usage: 0 kB
(6 rows)
同じInteger型の列に定義した主キーの範囲検索で
あっても、ハッシュインデックスではインデックスが効かない
© 2023 NTT DATA Corporation 13
YugabyteDBのユニークな処理 – remote filter -
YugabyteDBではストレージ層のKVS(DocDB)からデータを読み取り、YSQLの層(postgresのバックエンドプロセス)でFilter
や結合を実施する。そのためSeqScanなどは大量のデータをDocDBから読み込むことになる。
=# EXPLAIN (ANALYZE on,DIST on,COSTS off) SELECT * FROM h_t1 WHERE c1 < 100;
QUERY PLAN
-------------------------------------------------------------------------------
Seq Scan on h_t1 (actual time=13.273..3742.157 rows=99 loops=1)
Filter: (c1 < 100)
Rows Removed by Filter: 599901
Storage Table Read Requests: 588
Storage Table Execution Time: 3636.899 ms
Planning Time: 0.058 ms
Execution Time: 3742.478 ms
Storage Read Requests: 588
Storage Write Requests: 0
Storage Execution Time: 3636.899 ms
Peak Memory Usage: 0 kB
(11 rows)
Tserver
YSQL
DocDB
データ
ここでFilterや結合、
集計を実施
Tserver
DocDB
Tserver
DocDB
© 2023 NTT DATA Corporation 14
YugabyteDBのユニークな処理 – remote filter -
YugabyteDBではDocDB側へ一部のFilter演算をPushdownし、データのリクエスト量・回数を抑えることが可能。
Pushdownされた処理はRemote Filterとして表示される。
=# SET yb_enable_expression_pushdown TO on;
SET
=# EXPLAIN (ANALYZE on,DIST on,COSTS off) SELECT * FROM h_t1 WHERE c1 < 100;
QUERY PLAN
-------------------------------------------------------------------------------
Seq Scan on h_t1 (actual time=1211.024..2408.519 rows=99 loops=1)
Remote Filter: (c1 < 100)
Storage Table Read Requests: 2
Storage Table Execution Time: 2406.933 ms
Planning Time: 0.061 ms
Execution Time: 2408.693 ms
Storage Read Requests: 2
Storage Write Requests: 0
Storage Execution Time: 2406.933 ms
Peak Memory Usage: 14 kB
(10 rows)
=# EXPLAIN (ANALYZE on,DIST on,COSTS off) SELECT * FROM h_t1 WHERE c1 < 100;
QUERY PLAN
-----------------------------------------------------------------------------
--
Seq Scan on h_t1 (actual time=13.273..3742.157 rows=99 loops=1)
Filter: (c1 < 100)
Rows Removed by Filter: 599901
Storage Table Read Requests: 588
Storage Table Execution Time: 3636.899 ms
Planning Time: 0.058 ms
Execution Time: 3742.478 ms
Storage Read Requests: 588
Storage Write Requests: 0
Storage Execution Time: 3636.899 ms
Peak Memory Usage: 0 kB
(11 rows)
Remote Filterが有効に働くと、Storage~のリクエスト数などが
低減し、性能が向上することがある。
© 2023 NTT DATA Corporation 15
YugabyteDBのユニークな処理 – batched nested loop -
YugabyteDBではDocDB側からRPC経由でデータを取得するため、Nested Loopのような処理はNWレイテンシの影響など
を受けやすい。Range分割しているキーで範囲検索をするとある程度まとめてデータを取得できるが、Innerのテーブルへの検索
は多くのLoopとなる。
=# EXPLAIN (ANALYZE on, DIST on, COSTS off, TIMING off)
SELECT * FROM r_t1 r1, r_t2 r2 WHERE r1.c1 = r2.c1 AND r1.c1 < 2000;
QUERY PLAN
------------------------------------------------------------------------
Nested Loop (actual rows=1999 loops=1)
-> Index Scan using r_t1_pkey on r_t1 r1 (actual rows=1999 loops=1)
Index Cond: (c1 < 2000)
Storage Index Read Requests: 2
-> Index Scan using r_t2_pkey on r_t2 r2 (actual rows=1 loops=1999)
Index Cond: (c1 = r1.c1)
Storage Index Read Requests: 1
Planning Time: 0.116 ms
Execution Time: 309.301 ms
Storage Read Requests: 2001
Storage Write Requests: 0
Storage Execution Time: 262.997 ms
Peak Memory Usage: 24 kB
(13 rows)
Innerテーブルとなるr_t2に1999回のアクセス
Tserver
YSQL
DocDB
ここでFilterや結合、
集計を実施
Tserver
DocDB
Tserver
DocDB
© 2023 NTT DATA Corporation 16
YugabyteDBのユニークな処理 – batched nested loop -
YugabyteDBではyb_bnl_batch_sizeという動的に変更できるパラメータがあり、
「ANY(ARRAY[指定した数値分のデータ])」を利用してバッチ的にInnerテーブルへ引き当てに行く。
=# SET yb_bnl_batch_size = 5;
=# EXPLAIN (ANALYZE on, DIST on, COSTS off, TIMING off)
SELECT * FROM r_t1 r1, r_t2 r2 WHERE r1.c1 = r2.c1 AND r1.c1 < 2000;
QUERY PLAN
------------------------------------------------------------------------
YB Batched Nested Loop Join (actual rows=1999 loops=1)
Join Filter: (r1.c1 = r2.c1)
-> Index Scan using r_t1_pkey on r_t1 r1 (actual rows=1999 loops=1)
Index Cond: (c1 < 2000)
Storage Index Read Requests: 2
-> Index Scan using r_t2_pkey on r_t2 r2 (actual rows=5 loops=400)
Index Cond: (c1 = ANY (ARRAY[r1.c1, $1, $2, $3, $4]))
Storage Index Read Requests: 3
Planning Time: 0.134 ms
Execution Time: 210.351 ms
Storage Read Requests: 1202
Storage Write Requests: 0
Storage Execution Time: 183.998 ms
Peak Memory Usage: 237 kB
batch_sizeを5にすると、一度のIndex Scanで5件の検索をまとめて行う。
結果的にDocDBへのリクエスト数も減り、性能向上する。
(このケースだとsizeを100に引き上げると40msec程度までレスポンスタイムが改善。)
© 2023 NTT DATA Corporation 17
YugabyteDBのユニークなポイント
現時点のYugabyteDBは統計情報を収集しておらず、また活用することもしない。つまりルールベース オプティマイズと同様。
内部では固定値の行見積値を使っているため、想定行数は一定となる。また基本的にインデックスが使える場合はIndex Scan
を使用するようになる。ANALYZEはbeta機能として利用可能。
=# EXPLAIN SELECT * FROM r_t1 WHERE c1 = 1; -- 主キーで1件
QUERY PLAN
-----------------------------------------------------------------------
Index Scan using r_t1_pkey on r_t1 (cost=0.00..4.11 rows=1 width=52)
Index Cond: (c1 = 1)
(2 rows)
=# EXPLAIN SELECT * FROM r_t1 WHERE c1 < 100; -- 主キー範囲で99件
QUERY PLAN
-----------------------------------------------------------------------
Index Scan using r_t1_pkey on r_t1 (cost=0.00..4.11 rows=1 width=52)
Index Cond: (c1 < 100)
(2 rows)
=# EXPLAIN SELECT * FROM r_t1 WHERE c1 > 0; -- 主キー範囲で60万件
QUERY PLAN
-----------------------------------------------------------------------
Index Scan using r_t1_pkey on r_t1 (cost=0.00..4.11 rows=1 width=52)
Index Cond: (c1 > 0)
(2 rows)
© 2023 NTT DATA Corporation 18
YugabyteDBのユニークなポイント
前述のとおり統計情報を利用せず、インデックススキャンを積極的に利用する傾向が強いため、必然的にNested Loop結合が
選択されやすい。もともとYugabyteDBでは大量データのスキャンなどは得意としていないので、比較的多くの行を選択したり結
合する場合、HINT句の活用を視野に入れる必要がある。
=# EXPLAIN ANALYZE SELECT * FROM r_t1 r JOIN h_t1 h ON r.c1 = h.c1 WHERE r.c1 < 1000000;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------
Nested Loop (cost=0.00..8.23 rows=1 width=104) (actual time=8.286..244997.931 rows=600000 loops=1)
-> Index Scan using r_t1_pkey on r_t1 r (cost=0.00..4.11 rows=1 width=52) (actual time=7.775..1382.285 rows=600000 loops=1)
Index Cond: (c1 < 1000000)
-> Index Scan using h_t1_pkey on h_t1 h (cost=0.00..4.11 rows=1 width=52) (actual time=0.387..0.387 rows=1 loops=600000)
Index Cond: (c1 = r.c1)
Planning Time: 0.212 ms
Execution Time: 245603.057 ms
Peak Memory Usage: 32 kB
(8 rows)
=# /*+ HashJoin(r h) */ EXPLAIN ANALYZE SELECT * FROM r_t1 r JOIN h_t1 h ON r.c1 = h.c1 WHERE r.c1 < 1000000;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------
Hash Join (cost=4.12..106.76 rows=1 width=104) (actual time=4548.694..9061.421 rows=600000 loops=1)
Hash Cond: (h.c1 = r.c1)
-> Seq Scan on h_t1 h (cost=0.00..100.00 rows=1000 width=52) (actual time=6.727..3051.250 rows=600000 loops=1)
-> Hash (cost=4.11..4.11 rows=1 width=52) (actual time=4541.308..4541.309 rows=600000 loops=1)
Buckets: 65536 (originally 1024) Batches: 16 (originally 1) Memory Usage: 3725kB
-> Index Scan using r_t1_pkey on r_t1 r (cost=0.00..4.11 rows=1 width=52) (actual time=7.352..3880.254 rows=600000 loops=1)
Index Cond: (c1 < 1000000)
Planning Time: 0.294 ms
Execution Time: 9503.739 ms
Peak Memory Usage: 5899 kB
(10 rows)
© 2023 NTT DATA Corporation 19
まとめ
YugabyteDBでの実行計画の取得方法と簡単な見方、およびYugabyteDB特有の実行計画に関する機能・仕組みを紹介し
ました。PostgreSQLに慣れた方ならば、それと気づかずにYugabyteDBの実行計画を読めてしまうかもしれません。
どんなDBMSであっても実行計画の読み解きは必要となるスキルなので、ぜひ色々なクエリ、DBMSの実行計画を読んでみましょう。
© 2023 NTT DATA Corporation 20
参考
YugabyteDBのEXPLAIN
https://docs.yugabyte.com/preview/api/ysql/the-sql-language/statements/perf_explain/
PostgreSQLのEXPLAIN
https://www.postgresql.org/docs/current/sql-explain.html
YugabyteDBのHINT句利用方法
https://docs.yugabyte.com/preview/explore/query-1-performance/pg-hint-plan/
© 2022 NTT DATA Corporation
その他、記載されている会社名、商品名、又はサービス名は、
各社の登録商標又は商標です。

More Related Content

PDF
あなたの知らないPostgreSQL監視の世界
PDF
PostgreSQLのリカバリ超入門(もしくはWAL、CHECKPOINT、オンラインバックアップの仕組み)
PDF
YugabyteDBを使ってみよう - part2 -(NewSQL/分散SQLデータベースよろず勉強会 #2 発表資料)
PDF
いまさら聞けないPostgreSQL運用管理
PPTX
PostgreSQLの統計情報について(第26回PostgreSQLアンカンファレンス@オンライン 発表資料)
PPTX
PostgreSQL開発コミュニティに参加しよう! ~2022年版~(Open Source Conference 2022 Online/Kyoto 発...
PPTX
フックを使ったPostgreSQLの拡張機能を作ってみよう!(第33回PostgreSQLアンカンファレンス@オンライン 発表資料)
PPTX
SQLチューニング入門 入門編
あなたの知らないPostgreSQL監視の世界
PostgreSQLのリカバリ超入門(もしくはWAL、CHECKPOINT、オンラインバックアップの仕組み)
YugabyteDBを使ってみよう - part2 -(NewSQL/分散SQLデータベースよろず勉強会 #2 発表資料)
いまさら聞けないPostgreSQL運用管理
PostgreSQLの統計情報について(第26回PostgreSQLアンカンファレンス@オンライン 発表資料)
PostgreSQL開発コミュニティに参加しよう! ~2022年版~(Open Source Conference 2022 Online/Kyoto 発...
フックを使ったPostgreSQLの拡張機能を作ってみよう!(第33回PostgreSQLアンカンファレンス@オンライン 発表資料)
SQLチューニング入門 入門編

What's hot (20)

PDF
統計情報のリセットによるautovacuumへの影響について(第39回PostgreSQLアンカンファレンス@オンライン 発表資料)
PDF
YugabyteDBを使ってみよう(NewSQL/分散SQLデータベースよろず勉強会 #1 発表資料)
PDF
PostgreSQLレプリケーション10周年!徹底紹介!(PostgreSQL Conference Japan 2019講演資料)
PDF
Vacuum徹底解説
PPTX
スケールアウトするPostgreSQLを目指して!その第一歩!(NTTデータ テクノロジーカンファレンス 2020 発表資料)
PDF
PostgreSQLの運用・監視にまつわるエトセトラ
PDF
アーキテクチャから理解するPostgreSQLのレプリケーション
PDF
トランザクション処理可能な分散DB 「YugabyteDB」入門(Open Source Conference 2022 Online/Fukuoka 発...
PDF
pg_walinspectについて調べてみた!(第37回PostgreSQLアンカンファレンス@オンライン 発表資料)
PDF
PostgreSQLレプリケーション徹底紹介
PPTX
Apache Spark on Kubernetes入門(Open Source Conference 2021 Online Hiroshima 発表資料)
PPTX
PostgreSQLのfull_page_writesについて(第24回PostgreSQLアンカンファレンス@オンライン 発表資料)
PPTX
祝!PostgreSQLレプリケーション10周年!徹底紹介!!
PDF
PostgreSQL13でのレプリケーション関連の改善について(第14回PostgreSQLアンカンファレンス@オンライン)
PDF
まずやっとくPostgreSQLチューニング
PDF
速習!論理レプリケーション ~基礎から最新動向まで~(PostgreSQL Conference Japan 2022 発表資料)
PPTX
押さえておきたい、PostgreSQL 13 の新機能!! (PostgreSQL Conference Japan 2020講演資料)
PPTX
大規模データ活用向けストレージレイヤソフトのこれまでとこれから(NTTデータ テクノロジーカンファレンス 2019 講演資料、2019/09/05)
PPTX
pg_bigmで全文検索するときに気を付けたい5つのポイント(第23回PostgreSQLアンカンファレンス@オンライン 発表資料)
PDF
Dockerからcontainerdへの移行
統計情報のリセットによるautovacuumへの影響について(第39回PostgreSQLアンカンファレンス@オンライン 発表資料)
YugabyteDBを使ってみよう(NewSQL/分散SQLデータベースよろず勉強会 #1 発表資料)
PostgreSQLレプリケーション10周年!徹底紹介!(PostgreSQL Conference Japan 2019講演資料)
Vacuum徹底解説
スケールアウトするPostgreSQLを目指して!その第一歩!(NTTデータ テクノロジーカンファレンス 2020 発表資料)
PostgreSQLの運用・監視にまつわるエトセトラ
アーキテクチャから理解するPostgreSQLのレプリケーション
トランザクション処理可能な分散DB 「YugabyteDB」入門(Open Source Conference 2022 Online/Fukuoka 発...
pg_walinspectについて調べてみた!(第37回PostgreSQLアンカンファレンス@オンライン 発表資料)
PostgreSQLレプリケーション徹底紹介
Apache Spark on Kubernetes入門(Open Source Conference 2021 Online Hiroshima 発表資料)
PostgreSQLのfull_page_writesについて(第24回PostgreSQLアンカンファレンス@オンライン 発表資料)
祝!PostgreSQLレプリケーション10周年!徹底紹介!!
PostgreSQL13でのレプリケーション関連の改善について(第14回PostgreSQLアンカンファレンス@オンライン)
まずやっとくPostgreSQLチューニング
速習!論理レプリケーション ~基礎から最新動向まで~(PostgreSQL Conference Japan 2022 発表資料)
押さえておきたい、PostgreSQL 13 の新機能!! (PostgreSQL Conference Japan 2020講演資料)
大規模データ活用向けストレージレイヤソフトのこれまでとこれから(NTTデータ テクノロジーカンファレンス 2019 講演資料、2019/09/05)
pg_bigmで全文検索するときに気を付けたい5つのポイント(第23回PostgreSQLアンカンファレンス@オンライン 発表資料)
Dockerからcontainerdへの移行
Ad

Similar to YugabyteDBの実行計画を眺める(NewSQL/分散SQLデータベースよろず勉強会 #3 発表資料) (20)

PPTX
PostgreSQLクエリ実行の基礎知識 ~Explainを読み解こう~
PDF
より深く知るオプティマイザとそのチューニング
PPT
20090107 Postgre Sqlチューニング(Sql編)
PDF
Introduction of Oracle Database Architecture
PDF
PostgreSQL18新機能紹介(db tech showcase 2025 発表資料)
PDF
2019年度 若手技術者向け講座 実行計画
PDF
JPUGしくみ+アプリケーション勉強会(第20回)
PDF
PostgreSQL17対応版 EXPLAINオプションについて (第49回PostgreSQLアンカンファレンス@東京 発表資料)
PDF
pg_trgmと全文検索
PDF
PostgreSQL 9.2 新機能 - 新潟オープンソースセミナー2012
PDF
PostgreSQL実行計画入門@関西PostgreSQL勉強会
PDF
PostgreSQL SQLチューニング入門 実践編(pgcon14j)
PDF
プロとしてのOracleアーキテクチャ入門 ~番外編~ @ Developers Summit 2009
ODP
PostgreSQL 9.2 新機能 - OSC 2012 Kansai@Kyoto
PDF
PostgreSQLによるデータ分析ことはじめ
PDF
PostgreSQL 12の話
PDF
PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)
PPTX
実行統計による実践的SQLチューニング
PDF
Oracleの実行計画を読んでみよう! #dbts2017
PDF
アナリティクスをPostgreSQLで始めるべき10の理由@第6回 関西DB勉強会
PostgreSQLクエリ実行の基礎知識 ~Explainを読み解こう~
より深く知るオプティマイザとそのチューニング
20090107 Postgre Sqlチューニング(Sql編)
Introduction of Oracle Database Architecture
PostgreSQL18新機能紹介(db tech showcase 2025 発表資料)
2019年度 若手技術者向け講座 実行計画
JPUGしくみ+アプリケーション勉強会(第20回)
PostgreSQL17対応版 EXPLAINオプションについて (第49回PostgreSQLアンカンファレンス@東京 発表資料)
pg_trgmと全文検索
PostgreSQL 9.2 新機能 - 新潟オープンソースセミナー2012
PostgreSQL実行計画入門@関西PostgreSQL勉強会
PostgreSQL SQLチューニング入門 実践編(pgcon14j)
プロとしてのOracleアーキテクチャ入門 ~番外編~ @ Developers Summit 2009
PostgreSQL 9.2 新機能 - OSC 2012 Kansai@Kyoto
PostgreSQLによるデータ分析ことはじめ
PostgreSQL 12の話
PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)
実行統計による実践的SQLチューニング
Oracleの実行計画を読んでみよう! #dbts2017
アナリティクスをPostgreSQLで始めるべき10の理由@第6回 関西DB勉強会
Ad

More from NTT DATA Technology & Innovation (20)

PDF
開発中の新機能 Spark Declarative Pipeline に飛びついてみたが難しかった(JEDAI DAIS Recap#2 講演資料)
PDF
PGConf.dev 2025 参加レポート (JPUG総会併設セミナー2025 発表資料)
PDF
Can We Use Rust to Develop Extensions for PostgreSQL? (POSETTE: An Event for ...
PDF
つくって壊して直して学ぶ Database on Kubernetes (CloudNative Days Summer 2025 発表資料)
PDF
2025年現在のNewSQL (最強DB講義 #36 発表資料)
PDF
Java in Japan: A Journey of Community, Culture, and Global Integration (JavaO...
PDF
Unveiling the Hidden Layers of Java Class Files: Beyond Bytecode (Devnexus 2025)
PDF
論理レプリケーションのアーキテクチャ (第52回 PostgreSQLアンカンファレンス@オンライン 発表資料)
PDF
実はアナタの身近にある!? Linux のチェックポイント/レストア機能 (NTT Tech Conference 2025 発表資料)
PDF
Apache Sparkに対するKubernetesのNUMAノードを意識したリソース割り当ての性能効果 (Open Source Conference ...
PDF
PostgreSQL最新動向 ~カラムナストアから生成AI連携まで~ (Open Source Conference 2025 Tokyo/Spring ...
PDF
pgbenchのスレッドとクライアント (第51回 PostgreSQLアンカンファレンス@オンライン 発表資料)
PDF
PostgreSQLのgitレポジトリから見える2024年の開発状況 (第51回 PostgreSQLアンカンファレンス@オンライン 発表資料)
PDF
ストリーム処理はデータを失うから怖い?それ、何とかできますよ! 〜Apahe Kafkaを用いたストリーム処理における送達保証〜 (Open Source...
PDF
生成AI時代のPostgreSQLハイブリッド検索 (第50回PostgreSQLアンカンファレンス@オンライン 発表資料)
PDF
DAIS2024参加報告 ~Spark中心にしらべてみた~ (JEDAI DAIS Recap 講演資料)
PDF
PostgreSQLのHTAP適応について考える (PostgreSQL Conference Japan 2024 講演資料)
PDF
静かに変わってきたクラスファイルを詳細に調べて楽しむ(JJUG CCC 2024 Fall講演資料)
PDF
Gartnerも注目するグリーンソフトウェアの実現に向けて (Green Software Foundation Global Summit 2024 T...
PDF
パーティションのATTACH時の注意ポイント (第49回PostgreSQLアンカンファレンス@東京 発表資料)
開発中の新機能 Spark Declarative Pipeline に飛びついてみたが難しかった(JEDAI DAIS Recap#2 講演資料)
PGConf.dev 2025 参加レポート (JPUG総会併設セミナー2025 発表資料)
Can We Use Rust to Develop Extensions for PostgreSQL? (POSETTE: An Event for ...
つくって壊して直して学ぶ Database on Kubernetes (CloudNative Days Summer 2025 発表資料)
2025年現在のNewSQL (最強DB講義 #36 発表資料)
Java in Japan: A Journey of Community, Culture, and Global Integration (JavaO...
Unveiling the Hidden Layers of Java Class Files: Beyond Bytecode (Devnexus 2025)
論理レプリケーションのアーキテクチャ (第52回 PostgreSQLアンカンファレンス@オンライン 発表資料)
実はアナタの身近にある!? Linux のチェックポイント/レストア機能 (NTT Tech Conference 2025 発表資料)
Apache Sparkに対するKubernetesのNUMAノードを意識したリソース割り当ての性能効果 (Open Source Conference ...
PostgreSQL最新動向 ~カラムナストアから生成AI連携まで~ (Open Source Conference 2025 Tokyo/Spring ...
pgbenchのスレッドとクライアント (第51回 PostgreSQLアンカンファレンス@オンライン 発表資料)
PostgreSQLのgitレポジトリから見える2024年の開発状況 (第51回 PostgreSQLアンカンファレンス@オンライン 発表資料)
ストリーム処理はデータを失うから怖い?それ、何とかできますよ! 〜Apahe Kafkaを用いたストリーム処理における送達保証〜 (Open Source...
生成AI時代のPostgreSQLハイブリッド検索 (第50回PostgreSQLアンカンファレンス@オンライン 発表資料)
DAIS2024参加報告 ~Spark中心にしらべてみた~ (JEDAI DAIS Recap 講演資料)
PostgreSQLのHTAP適応について考える (PostgreSQL Conference Japan 2024 講演資料)
静かに変わってきたクラスファイルを詳細に調べて楽しむ(JJUG CCC 2024 Fall講演資料)
Gartnerも注目するグリーンソフトウェアの実現に向けて (Green Software Foundation Global Summit 2024 T...
パーティションのATTACH時の注意ポイント (第49回PostgreSQLアンカンファレンス@東京 発表資料)

YugabyteDBの実行計画を眺める(NewSQL/分散SQLデータベースよろず勉強会 #3 発表資料)

  • 1. © 2023 NTT DATA Corporation © 2023 NTT DATA Corporation NewSQL/分散SQLデータベース よろず勉強会 #3 YugabyteDBの実行計画を眺める 2023年2月16日 NTTデータ 笠原辰仁
  • 2. © 2023 NTT DATA Corporation 2 自己紹介 • 笠原 辰仁 (@kasa_zip) • 長年PostgreSQLの検証や周辺ツールの開発、サポートなどに従事 • 最近はNewSQLや分散データベースに属するOSSプロダクトの調査や検証、 適用領域の見極めなど • 本日は、分散データベースのOSSプロダクトであるYugabyteDBの実行計画の取得方法や 情報の見方を解説
  • 3. © 2023 NTT DATA Corporation 3 実行計画とは 発行されたクエリをどのように実行するかをDBMSが生成する情報。一般的にはDBMSのPlannerやOptimizerと呼ばれる機能 が生成する。 通常、あまりユーザ(クエリを発行する人)が実行計画を意識することは無いが、思ったような性能が出ない場合の原因解析やクエ リチューニングを行った効果などを調査したい時に、とても有用なもの。 SELECT * FROM t1 JOIN t2 ON t1.c1 = t2.c1 WHERE t1.c1 < 10; QUERY PLAN -------------------------------------- Nested Loop Join Filter: (t1.c1 = t2.c1) -> Index Scan using t1_pkey on t1 Index Cond: (c1 < 10) -> Seq Scan on t2 YugabyteDB (のPlanner)
  • 4. © 2023 NTT DATA Corporation 4 実行計画の取得方法 YugabyteDBでは他のDBMSと同様にEXPLAINという句をクエリの先頭に付与することで実行計画を取得できる。 クエリは実際には実行されない。出力される情報はPostgreSQLとほぼ同じ。 yugabyte=# EXPLAIN SELECT * FROM r_t1 WHERE c1 < 100; QUERY PLAN ----------------------------------------------------------------------- Index Scan using r_t1_pkey on r_t1 (cost=0.00..4.11 rows=1 width=52) Index Cond: (c1 < 100) (2 rows) yugabyte=# EXPLAIN SELECT * FROM r_t1; QUERY PLAN ---------------------------------------------------------- Seq Scan on r_t1 (cost=0.00..100.00 rows=1000 width=52) (1 row) yugabyte=# EXPLAIN SELECT * FROM r_t1 r JOIN h_t1 h ON r.c1 = h.c1 WHERE r.c1 < 100; QUERY PLAN ------------------------------------------------------------------------------- Nested Loop (cost=0.00..8.23 rows=1 width=104) -> Index Scan using r_t1_pkey on r_t1 r (cost=0.00..4.11 rows=1 width=52) Index Cond: (c1 < 100) -> Index Scan using h_t1_pkey on h_t1 h (cost=0.00..4.11 rows=1 width=52) Index Cond: (c1 = r.c1) (5 rows)
  • 5. © 2023 NTT DATA Corporation 5 実行計画の取得方法 EXPLAINではオプションをいくつか付与することで様々な情報を出力できる。 オプション 説明 ANALYZE 指定したクエリを実行し、実際の所要時間や消費した各種リソース(IOやメモリなど)の情報を出力する。 VERBOSE SELECT列の射影対象や中間処理での出力対象を出力する。 COSTS 実行計画のコスト情報を出力する。デフォルト有効。 TIMING 実行時の所要時間を出力する。ANALYZEの指定が必須でデフォルト有効。 BUFFERS 実行過程における巨大なハッシュやソート処理の一時ファイル書き出しで使用されたバッファサイズを出力す る。ANALYZEの指定が必須。 SUMMARY 実行計画の末尾にプラン作成時間、実行時間、総メモリ消費量などを出力する。デフォルト有効。 FORMAT 実行計画情報の出力形式を指定する。TEXT、JSON、YAML、XMLから選択できデフォルトはTEXT。 DIST ストレージ層のDocDBへの読み書きリクエスト数やDocDBでの所要時間を出力する。 ANALYZEオプションを付与することで実際の所要時間が分かるため多用することが多い。ただし実際にクエリが実行されるため更 新系の処理を対象にするときは注意。(BEGIN; ABORT;で囲うなど工夫がいる) COSTSやTIMING、SUMMARYについては変動要素の強い出力情報になるので、リグレッションテストなどの出力と期待のdiff を取るときなどのノイズ除去として用いられたり、実行計画を簡潔に出力したい場合などに用いる。
  • 6. © 2023 NTT DATA Corporation 6 EXPLAINの文法 EXPLAINでは複数のオプションを組み合わせて使用できる。以下のようにEXPLAIN (オプション [,..]) の形で指定する。 EXPLAIN (ANALYZE, BUFFERS, VERBOSE) SELECT … 上記はANALYZE、BUFFERS、VERBOSEを有効にしている。オプション [on | off] の形を取ることもできる。 EXPLAIN (ANALYZE on, BUFFERS on, COSTS off) SELECT … 上記はANALYZE、BUFFERSを有効にし、COSTSを無効にしている。 EXPLAINは通常のSELECTやUPDATEなどのクエリの他、カーソルのDECLARE、準備文(Prepared Statement)に対する EXECUTEにも使用することができる。 PREPARE p1(int) AS SELECT … WHERE c1 = $1; EXPLAIN (ANALYZE on, BUFFERS on) EXECUTE p1(10); EXPLAIN (ANALYZE on, BUFFERS on) DECLARE cur FOR SELECT …
  • 7. © 2023 NTT DATA Corporation 7 実行計画の見方 => EXPLAIN SELECT * FROM r_t1 r JOIN h_t1 h ON r.c1 = h.c1 WHERE h.c1 < 10; QUERY PLAN ------------------------------------------------------------------------------- Nested Loop (cost=0.00..216.39 rows=1000 width=104) -> Seq Scan on h_t1 h (cost=0.00..102.50 rows=1000 width=52) Filter: (c1 < 10) -> Index Scan using r_t1_pkey on r_t1 r (cost=0.00..0.11 rows=1 width=52) Index Cond: (c1 = h.c1) (5 rows) 赤字部分はノードタイプとも呼ばれ、実行されるスキャン、 結合、集計等の各処理の種別を表す。 基本的にネストの深い方(右の方)から順次実行されていく 代表的なノードタイプには以下がある。 • スキャン:Seq Scan/Index Scan/Index Only Scan • 結合:Nested Loop/Merge Join/Hash Join (Semi/Anti) • 集計:HashAggregate/GroupAggregate • 更新:Insert/Update/Delete • その他:Sort/Limit/Result/Append… など。 ちなみにPostgreSQLにあるBitmapScanは無い まず計画そのものとなるノード情報。
  • 8. © 2023 NTT DATA Corporation 8 実行計画の見方 => EXPLAIN SELECT * FROM r_t1 r JOIN h_t1 h ON r.c1 = h.c1 WHERE h.c1 < 10; QUERY PLAN ------------------------------------------------------------------------------- Nested Loop (cost=0.00..216.39 rows=1000 width=104) -> Seq Scan on h_t1 h (cost=0.00..102.50 rows=1000 width=52) Filter: (c1 < 10) -> Index Scan using r_t1_pkey on r_t1 r (cost=0.00..0.11 rows=1 width=52) Index Cond: (c1 = h.c1) (5 rows) 赤字部分はコストに関する情報で、N.NN .. M.MMはそれぞれ スタートアップコスト(そのノードを開始するための準備コスト)と トータルコスト(ノード処理を一通り完了するまでの総コスト)。 rowsは各ノードで取得する予想行数。 widthは各ノードで取得する列幅の総サイズ。 コストの計算式はPostgreSQLと同様のロジックだが、 YugabyteDB特有の要素がいくつかある。(異なるゾーン やリージョンへの問い合わせコストは別途追加するなど) src/backend/access/yb_access/yb_scan.cの ybcCostEstimate() Plannerが実行計画の作成の根拠とした見積情報。
  • 9. © 2023 NTT DATA Corporation 9 実行計画の見方 => EXPLAIN (ANALYZE on, COSTS off) SELECT r.c1, r.c4 FROM r_t1 r JOIN h_t1 h ON r.c1 = h.c1 WHERE h.c1 < 100; QUERY PLAN --------------------------------------------------------------------------------------- Nested Loop (actual time=12.706..1979.256 rows=99 loops=1) -> Seq Scan on h_t1 h (actual time=7.545..1669.513 rows=99 loops=1) Filter: (c1 < 100) Rows Removed by Filter: 599901 -> Index Scan using r_t1_pkey on r_t1 r (actual time=3.108..3.108 rows=1 loops=99) Index Cond: (c1 = h.c1) Planning Time: 0.127 ms Execution Time: 1979.423 ms Peak Memory Usage: 30 kB (9 rows) 赤字部分は実際にかかった時間や取得した行数情報。 actual timeのNN.NN .. MM.MMは各ノードで最初の1行を取得す るまでの時間(ms)と最後の行を取得するまでの時間(ms)。 rowsは各ノードで取得された件数。 loopsは各ノードが繰り返された回数。 Rows Removed by Filterはスキャンした件数のうち条件により除去 された件数。 loopsが2以上の場合、実際にかかる時間は 「actual time」 * 「loops回数」となる。 loopsが多いものはactual timeが短くても注意すると良い。 実際にクエリを実行した場合の所要時間や取得した件数などの情報。
  • 10. © 2023 NTT DATA Corporation 10 実行計画の見方 => EXPLAIN (ANALYZE on, COSTS off) SELECT r.c1, r.c4 FROM r_t1 r JOIN h_t1 h ON r.c1 = h.c1 WHERE h.c1 < 100; QUERY PLAN --------------------------------------------------------------------------------------- Nested Loop (actual time=12.706..1979.256 rows=99 loops=1) -> Seq Scan on h_t1 h (actual time=7.545..1669.513 rows=99 loops=1) Filter: (c1 < 100) Rows Removed by Filter: 599901 -> Index Scan using r_t1_pkey on r_t1 r (actual time=3.108..3.108 rows=1 loops=99) Index Cond: (c1 = h.c1) Planning Time: 0.127 ms Execution Time: 1979.423 ms Peak Memory Usage: 30 kB (9 rows) 赤字部分はサマリ情報。 Planning Timeはプラン作成にかかった時間。 Execution Timeはクエリ処理にかかった総時間。 Peak Memory Usageはクエリ処理中の最もメモリを消費していた際 の利用量(Tserver上のpostgresバックエンドでの消費量)。 Execution TimeはYugabyteDB内での所要時間となり、 クライアントへ結果を返すなどの通信時間などは含まれない ので注意。 実際にクエリを実行した場合のサマリ情報。
  • 11. © 2023 NTT DATA Corporation 11 実行計画の見方 => EXPLAIN (ANALYZE on, DIST on, COSTS off) SELECT r.c1, r.c4 FROM r_t1 r JOIN h_t1 h ON r.c1 = h.c1 WHERE h.c1 < 100; QUERY PLAN --------------------------------------------------------------------------------------- Nested Loop (actual time=20.376..1765.325 rows=99 loops=1) -> Seq Scan on h_t1 h (actual time=6.409..1478.253 rows=99 loops=1) Filter: (c1 < 100) Rows Removed by Filter: 599901 Storage Table Read Requests: 588 Storage Table Execution Time: 1424.985 ms -> Index Scan using r_t1_pkey on r_t1 r (actual time=2.882..2.882 rows=1 loops=99) Index Cond: (c1 = h.c1) Storage Index Read Requests: 1 Storage Index Execution Time: 2.859 ms Planning Time: 0.085 ms Execution Time: 1765.460 ms Storage Read Requests: 687 Storage Write Requests: 0 Storage Execution Time: 1707.983 ms Peak Memory Usage: 30 kB (16 rows) 赤字部分はストレージ(DocDB)での処理時間や回数の情報。 Storage Table~はSeqScan処理でDocDBへ行われたRPCの回数と所要時間。 Storage Index~はIndex Scan処理でDocDBへ行われたRPCの回数と所要時 間。 Storage Read/Write RequestはDocDBへリクエストされたRPCの総回数。 Storage Execution TimeはDocDBでの処理総時間。 なお、loopsが2以上の場合はStorage~Requestsはその回数だけ実施される。 DISTオプションによる実際にクエリを実行した場合のDocDBでの処理時間やリクエスト回数などの情報。
  • 12. © 2023 NTT DATA Corporation 12 YugabyteDBのユニークな処理 – HashとRange - YugabyteDBではインデックスはデフォルトでハッシュインデックスが利用される。そのため範囲検索を多用する場合はインデックス 定義に注意しておく。 =# CREATE TABLE r_t1 (c1 int, c2 int, c3 int, c4 text, c5 timestamp, primary key (c1 ASC)); -- 主キーはRange =# CREATE TABLE h_t1 (c1 int, c2 int, c3 int, c4 text, c5 timestamp, primary key (c1)); -- 主キーはHash (各テーブルに60万件ほど投入) =# EXPLAIN (ANALYZE on, COSTS off) SELECT * FROM r_t1 WHERE c1 < 100; QUERY PLAN ------------------------------------------------------------------------------- Index Scan using r_t1_pkey on r_t1 (actual time=1.099..1.134 rows=99 loops=1) Index Cond: (c1 < 100) Planning Time: 0.055 ms Execution Time: 1.163 ms Peak Memory Usage: 0 kB (5 rows) =# EXPLAIN (ANALYZE on, COSTS off) SELECT * FROM h_t1 WHERE c1 < 100; QUERY PLAN ----------------------------------------------------------------- Seq Scan on h_t1 (actual time=19.090..2783.098 rows=99 loops=1) Filter: (c1 < 100) Rows Removed by Filter: 599901 Planning Time: 1.557 ms Execution Time: 2783.488 ms Peak Memory Usage: 0 kB (6 rows) 同じInteger型の列に定義した主キーの範囲検索で あっても、ハッシュインデックスではインデックスが効かない
  • 13. © 2023 NTT DATA Corporation 13 YugabyteDBのユニークな処理 – remote filter - YugabyteDBではストレージ層のKVS(DocDB)からデータを読み取り、YSQLの層(postgresのバックエンドプロセス)でFilter や結合を実施する。そのためSeqScanなどは大量のデータをDocDBから読み込むことになる。 =# EXPLAIN (ANALYZE on,DIST on,COSTS off) SELECT * FROM h_t1 WHERE c1 < 100; QUERY PLAN ------------------------------------------------------------------------------- Seq Scan on h_t1 (actual time=13.273..3742.157 rows=99 loops=1) Filter: (c1 < 100) Rows Removed by Filter: 599901 Storage Table Read Requests: 588 Storage Table Execution Time: 3636.899 ms Planning Time: 0.058 ms Execution Time: 3742.478 ms Storage Read Requests: 588 Storage Write Requests: 0 Storage Execution Time: 3636.899 ms Peak Memory Usage: 0 kB (11 rows) Tserver YSQL DocDB データ ここでFilterや結合、 集計を実施 Tserver DocDB Tserver DocDB
  • 14. © 2023 NTT DATA Corporation 14 YugabyteDBのユニークな処理 – remote filter - YugabyteDBではDocDB側へ一部のFilter演算をPushdownし、データのリクエスト量・回数を抑えることが可能。 Pushdownされた処理はRemote Filterとして表示される。 =# SET yb_enable_expression_pushdown TO on; SET =# EXPLAIN (ANALYZE on,DIST on,COSTS off) SELECT * FROM h_t1 WHERE c1 < 100; QUERY PLAN ------------------------------------------------------------------------------- Seq Scan on h_t1 (actual time=1211.024..2408.519 rows=99 loops=1) Remote Filter: (c1 < 100) Storage Table Read Requests: 2 Storage Table Execution Time: 2406.933 ms Planning Time: 0.061 ms Execution Time: 2408.693 ms Storage Read Requests: 2 Storage Write Requests: 0 Storage Execution Time: 2406.933 ms Peak Memory Usage: 14 kB (10 rows) =# EXPLAIN (ANALYZE on,DIST on,COSTS off) SELECT * FROM h_t1 WHERE c1 < 100; QUERY PLAN ----------------------------------------------------------------------------- -- Seq Scan on h_t1 (actual time=13.273..3742.157 rows=99 loops=1) Filter: (c1 < 100) Rows Removed by Filter: 599901 Storage Table Read Requests: 588 Storage Table Execution Time: 3636.899 ms Planning Time: 0.058 ms Execution Time: 3742.478 ms Storage Read Requests: 588 Storage Write Requests: 0 Storage Execution Time: 3636.899 ms Peak Memory Usage: 0 kB (11 rows) Remote Filterが有効に働くと、Storage~のリクエスト数などが 低減し、性能が向上することがある。
  • 15. © 2023 NTT DATA Corporation 15 YugabyteDBのユニークな処理 – batched nested loop - YugabyteDBではDocDB側からRPC経由でデータを取得するため、Nested Loopのような処理はNWレイテンシの影響など を受けやすい。Range分割しているキーで範囲検索をするとある程度まとめてデータを取得できるが、Innerのテーブルへの検索 は多くのLoopとなる。 =# EXPLAIN (ANALYZE on, DIST on, COSTS off, TIMING off) SELECT * FROM r_t1 r1, r_t2 r2 WHERE r1.c1 = r2.c1 AND r1.c1 < 2000; QUERY PLAN ------------------------------------------------------------------------ Nested Loop (actual rows=1999 loops=1) -> Index Scan using r_t1_pkey on r_t1 r1 (actual rows=1999 loops=1) Index Cond: (c1 < 2000) Storage Index Read Requests: 2 -> Index Scan using r_t2_pkey on r_t2 r2 (actual rows=1 loops=1999) Index Cond: (c1 = r1.c1) Storage Index Read Requests: 1 Planning Time: 0.116 ms Execution Time: 309.301 ms Storage Read Requests: 2001 Storage Write Requests: 0 Storage Execution Time: 262.997 ms Peak Memory Usage: 24 kB (13 rows) Innerテーブルとなるr_t2に1999回のアクセス Tserver YSQL DocDB ここでFilterや結合、 集計を実施 Tserver DocDB Tserver DocDB
  • 16. © 2023 NTT DATA Corporation 16 YugabyteDBのユニークな処理 – batched nested loop - YugabyteDBではyb_bnl_batch_sizeという動的に変更できるパラメータがあり、 「ANY(ARRAY[指定した数値分のデータ])」を利用してバッチ的にInnerテーブルへ引き当てに行く。 =# SET yb_bnl_batch_size = 5; =# EXPLAIN (ANALYZE on, DIST on, COSTS off, TIMING off) SELECT * FROM r_t1 r1, r_t2 r2 WHERE r1.c1 = r2.c1 AND r1.c1 < 2000; QUERY PLAN ------------------------------------------------------------------------ YB Batched Nested Loop Join (actual rows=1999 loops=1) Join Filter: (r1.c1 = r2.c1) -> Index Scan using r_t1_pkey on r_t1 r1 (actual rows=1999 loops=1) Index Cond: (c1 < 2000) Storage Index Read Requests: 2 -> Index Scan using r_t2_pkey on r_t2 r2 (actual rows=5 loops=400) Index Cond: (c1 = ANY (ARRAY[r1.c1, $1, $2, $3, $4])) Storage Index Read Requests: 3 Planning Time: 0.134 ms Execution Time: 210.351 ms Storage Read Requests: 1202 Storage Write Requests: 0 Storage Execution Time: 183.998 ms Peak Memory Usage: 237 kB batch_sizeを5にすると、一度のIndex Scanで5件の検索をまとめて行う。 結果的にDocDBへのリクエスト数も減り、性能向上する。 (このケースだとsizeを100に引き上げると40msec程度までレスポンスタイムが改善。)
  • 17. © 2023 NTT DATA Corporation 17 YugabyteDBのユニークなポイント 現時点のYugabyteDBは統計情報を収集しておらず、また活用することもしない。つまりルールベース オプティマイズと同様。 内部では固定値の行見積値を使っているため、想定行数は一定となる。また基本的にインデックスが使える場合はIndex Scan を使用するようになる。ANALYZEはbeta機能として利用可能。 =# EXPLAIN SELECT * FROM r_t1 WHERE c1 = 1; -- 主キーで1件 QUERY PLAN ----------------------------------------------------------------------- Index Scan using r_t1_pkey on r_t1 (cost=0.00..4.11 rows=1 width=52) Index Cond: (c1 = 1) (2 rows) =# EXPLAIN SELECT * FROM r_t1 WHERE c1 < 100; -- 主キー範囲で99件 QUERY PLAN ----------------------------------------------------------------------- Index Scan using r_t1_pkey on r_t1 (cost=0.00..4.11 rows=1 width=52) Index Cond: (c1 < 100) (2 rows) =# EXPLAIN SELECT * FROM r_t1 WHERE c1 > 0; -- 主キー範囲で60万件 QUERY PLAN ----------------------------------------------------------------------- Index Scan using r_t1_pkey on r_t1 (cost=0.00..4.11 rows=1 width=52) Index Cond: (c1 > 0) (2 rows)
  • 18. © 2023 NTT DATA Corporation 18 YugabyteDBのユニークなポイント 前述のとおり統計情報を利用せず、インデックススキャンを積極的に利用する傾向が強いため、必然的にNested Loop結合が 選択されやすい。もともとYugabyteDBでは大量データのスキャンなどは得意としていないので、比較的多くの行を選択したり結 合する場合、HINT句の活用を視野に入れる必要がある。 =# EXPLAIN ANALYZE SELECT * FROM r_t1 r JOIN h_t1 h ON r.c1 = h.c1 WHERE r.c1 < 1000000; QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------- Nested Loop (cost=0.00..8.23 rows=1 width=104) (actual time=8.286..244997.931 rows=600000 loops=1) -> Index Scan using r_t1_pkey on r_t1 r (cost=0.00..4.11 rows=1 width=52) (actual time=7.775..1382.285 rows=600000 loops=1) Index Cond: (c1 < 1000000) -> Index Scan using h_t1_pkey on h_t1 h (cost=0.00..4.11 rows=1 width=52) (actual time=0.387..0.387 rows=1 loops=600000) Index Cond: (c1 = r.c1) Planning Time: 0.212 ms Execution Time: 245603.057 ms Peak Memory Usage: 32 kB (8 rows) =# /*+ HashJoin(r h) */ EXPLAIN ANALYZE SELECT * FROM r_t1 r JOIN h_t1 h ON r.c1 = h.c1 WHERE r.c1 < 1000000; QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------- Hash Join (cost=4.12..106.76 rows=1 width=104) (actual time=4548.694..9061.421 rows=600000 loops=1) Hash Cond: (h.c1 = r.c1) -> Seq Scan on h_t1 h (cost=0.00..100.00 rows=1000 width=52) (actual time=6.727..3051.250 rows=600000 loops=1) -> Hash (cost=4.11..4.11 rows=1 width=52) (actual time=4541.308..4541.309 rows=600000 loops=1) Buckets: 65536 (originally 1024) Batches: 16 (originally 1) Memory Usage: 3725kB -> Index Scan using r_t1_pkey on r_t1 r (cost=0.00..4.11 rows=1 width=52) (actual time=7.352..3880.254 rows=600000 loops=1) Index Cond: (c1 < 1000000) Planning Time: 0.294 ms Execution Time: 9503.739 ms Peak Memory Usage: 5899 kB (10 rows)
  • 19. © 2023 NTT DATA Corporation 19 まとめ YugabyteDBでの実行計画の取得方法と簡単な見方、およびYugabyteDB特有の実行計画に関する機能・仕組みを紹介し ました。PostgreSQLに慣れた方ならば、それと気づかずにYugabyteDBの実行計画を読めてしまうかもしれません。 どんなDBMSであっても実行計画の読み解きは必要となるスキルなので、ぜひ色々なクエリ、DBMSの実行計画を読んでみましょう。
  • 20. © 2023 NTT DATA Corporation 20 参考 YugabyteDBのEXPLAIN https://docs.yugabyte.com/preview/api/ysql/the-sql-language/statements/perf_explain/ PostgreSQLのEXPLAIN https://www.postgresql.org/docs/current/sql-explain.html YugabyteDBのHINT句利用方法 https://docs.yugabyte.com/preview/explore/query-1-performance/pg-hint-plan/
  • 21. © 2022 NTT DATA Corporation その他、記載されている会社名、商品名、又はサービス名は、 各社の登録商標又は商標です。