OpenText Analytics Database 旧Vertica

技術情報サイト

Analytics Database

パフォーマンスを最大化するためのSQL記述ポイント

公開日:
更新日:
基本操作
チューニング
#チューニング
#実行計画

はじめに

複数のテーブルを何度も結合するような処理を実行する場合、処理の途中のデータセットが大きいと、大きなデータセットのまま後続の処理も実行するため、SQL実行時間が比較的長くなるケースがあります。
このような状況を避けるためには、処理の初期段階で出来る限りデータセットを小さくする(WHERE句で抽出データを絞る)ことが大切です。

しかしながら、SQLの記述内容によっては、WHERE句で条件を指定しても初期段階でデータセットが絞り込まれないケースがあります。
本記事では、上記のケースに該当するSQL記述内容を紹介します。
データセットが絞り込まれているか確認するためには、実行計画の「Rows」を確認します。

  • 読み込みデータ量が小さい例

/*** Rowsが4M(約400万行の読み込み)の実行例 ***/
dbadmin=> EXPLAIN
dbadmin-> SELECT count(*) FROM lineorder WHERE lo_orderdate = 19920101;
                                QUERY PLAN
---------------------------------------------------------------------------
 ------------------------------ 
 QUERY PLAN DESCRIPTION: 
 ------------------------------
 
 EXPLAIN
 SELECT count(*) FROM lineorder WHERE lo_orderdate = 19920101;
 
 Access Path:
 +-GROUPBY NOTHING [Cost: 2M, Rows: 1] (PATH ID: 1)
 |  Aggregates: count(*)
 | +---> STORAGE ACCESS for lineorder [Cost: 2M, Rows: 4M] (PATH ID: 2)  /* Rowsが4M */
 | |      Projection: public.LINEORDER_DBD_2_rep_d1223
 | |      Filter: (lineorder.LO_ORDERDATE = 19920101)

<以降、省略>
  • 読み込みデータ量が増加する例(上記の例よりも大きい)

/*** Rowsが750M(約7億5000万行の読み込み)の実行例 ***/
dbadmin=> EXPLAIN
dbadmin-> SELECT count(*) FROM lineorder WHERE lo_orderdate != 19920101;
                                QUERY PLAN
---------------------------------------------------------------------------
 ------------------------------ 
 QUERY PLAN DESCRIPTION: 
 ------------------------------
 
 EXPLAIN
 SELECT count(*) FROM lineorder WHERE lo_orderdate != 19920101;
 
 Access Path:
 +-GROUPBY NOTHING [Cost: 2M, Rows: 1] (PATH ID: 1)
 |  Aggregates: count(*)
 | +---> STORAGE ACCESS for lineorder [Cost: 2M, Rows: 750M] (PATH ID: 2) /* Rowsが750M(約7億5000万行の読み込み) */
 | |      Projection: public.LINEORDER_DBD_2_rep_d1223
 | |      Filter: (lineorder.LO_ORDERDATE <> 19920101)

<以降、省略>

SQL記述の留意事項

否定演算子を使用する場合

否定演算子を使用している場合は、読み込みデータ量が増加します。

  • 読み込みデータ量 “小”

dbadmin=> SELECT count(*) FROM lineorder WHERE lo_orderdate = 19920101;
  • 読み込みデータ量 “増”

dbadmin=> SELECT count(*) FROM lineorder WHERE lo_orderdate != 19920101;

WHERE句で指定する条件の左辺に関数を使用する場合

WHERE句で指定する条件の左辺に関数を使用する場合は、読み込みデータ量が増加します。

  • 読み込みデータ量 “小”

dbadmin=> SELECT count(*) FROM lineorder WHERE lo_orderdate = 19920101;
  • 読み込みデータ量 “増”

dbadmin=> SELECT count(*) FROM lineorder WHERE TO_CHAR(lo_orderdate) = '19920101';

LIKE演算子を使用して中間一致または後方一致で検索する場合

LIKE演算子を使用して中間一致または後方一致で検索する場合は、読み込みデータ量が増加します。

  • 読み込みデータ量 “小”

dbadmin=> SELECT count(*) FROM lineorder WHERE lo_orderpriority LIKE '1-URGEN%';
  • 読み込みデータ量 “増”

dbadmin=> SELECT count(*) FROM lineorder WHERE lo_orderpriority LIKE '%-URGENT';

dbadmin=> SELECT count(*) FROM lineorder WHERE lo_orderpriority LIKE '%-URGEN%';

IS NULL演算子を使用する場合

IS NULL演算子を使用する場合は、読み込みデータ量が増加します。

  • 読み込みデータ量 “増”

dbadmin=> SELECT count(*) FROM lineorder WHERE lo_orderdate IS NULL;

ビューを作成し、ビューに対して条件を指定する場合(1)

ビュー内のSELECTリストに検索条件項目への関数を含む場合、読み込みデータ量が増加します。

  • 本例で使用するオブジェクト

種類

オブジェクト名

トランザクションテーブル

「lineorder」

マスタテーブル

「date1」

ビュー1

「lo_view」

ビュー2

「lo_view2」

  • ビューの内容

dbadmin=> /***** ビュー1の内容 *****/
dbadmin=> CREATE OR REPLACE VIEW lo_view as
dbadmin-> SELECT
dbadmin->   l.lo_orderdate,
dbadmin->   l.lo_orderpriority,
dbadmin->   d.d_datekey,
dbadmin->   d.d_date
dbadmin-> FROM lineorder AS l
dbadmin->   LEFT OUTER JOIN date1 AS d ON l.lo_orderdate = d.d_datekey;
CREATE VIEW

dbadmin=> /***** ビュー2の内容 *****/
dbadmin=> CREATE OR REPLACE VIEW lo_view2 as
dbadmin-> SELECT
dbadmin->   l.lo_orderdate,
dbadmin->   SUBSTR(l.lo_orderpriority, 1, 8) AS lo_orderpriority,  /*** ビュー1と比較して関数を使用 ***/
dbadmin->   d.d_datekey,
dbadmin->   d.d_date
dbadmin-> FROM lineorder AS l
dbadmin->   LEFT OUTER JOIN date1 AS d ON l.lo_orderdate = d.d_datekey;
CREATE VIEW
  • 読み込みデータ量 “小”

dbadmin=> SELECT count(*) FROM lo_view WHERE lo_orderpriority='1-URGENT';
  • 読み込みデータ量 “増”

dbadmin=> SELECT count(*) FROM lo_view2 WHERE lo_orderpriority='1-URGENT';

ビューを作成し、ビューに対して条件を指定する場合(2)

外部結合を行うビューを作成し、そのビューに対して条件を指定する場合、以下の動作をとります。

・トランザクションテーブル(結合元)の項目を条件に指定した場合 … 読み込みデータ量が小さい
・マスタテーブル(結合先)の項目を条件に使用した場合 … 読み込みデータ量が増加

詳細は以下の記事をご参照ください。

<外部結合を行っているViewに条件を付けて検索する際の注意点>
https://www.ashisuto.co.jp/cm/analytics-database/outer_view.html

参考

<SQLの実行計画を確認する方法>
https://www.ashisuto.co.jp/cm/analytics-database/sql-plan.html

検証バージョンについて

この記事の内容はVertica 9.2で確認しています。

更新履歴

2020/02/28 誤植を修正(「IS NULL演算子を使用する場合」の箇所)
2019/12/26 本記事を公開