( BROADCAST )
6. DB の件数を考慮した記述
57
DBアクセス性能は、検索結果件数および検索中(SQL実行中)にアクセス
するデータ件数に大きく依存します。この場合のSQL
コーディングについて示 します。6-1 表の件数の取得
表の件数を求めるときは、以下を指定してください。
COUNT
(*)を使う。このとき可能な限りWITHOUT LOCK NOWAIT
を指定する。
条件式にはインデクスの定義された列を指定する。例を図 6-1-1に示します。
条件式に指定した列がインデクスの第一構成列でない場合、性能が悪くなることがありま す。
Point
表の件数を求めるとき、COUNT
(*)を使用すること○
SELECT COUNT(*) FROM ZAIKOWHERE ZSURYO > 10 WITHOUT LOCK NOWAIT ;
件数の取得には
COUNT
(*)を使用する。ZSURYO
にインデクスを定義する。図 6-1-1 件数の取得の
SQL
例DB
の件数を考慮した記述© Hitachi, Ltd. 2013 , 2015. All rights reserved.
6-2 データの存在有無の取得
59
データの存在チェックを行うときの留意事項を以下に記載します。
LIMIT 1
を指定して、1
件見つけたら処理を打ち切るようにする。
可能な限りWITHOUT LOCK NOWAIT
を指定する。
条件式と選択式にはインデクスの定義された列を指定する。 ORDER BY
は作業表を作成することがあるため、指定しない。例を図 6-2-1に示します。
Point
データの存在チェックにはLIMIT
を使用すること○
SELECT ZA.ZSURYO FROM ZAIKO ZAWHERE ZA.ZSURYO = 0 LIMIT 1
WITHOUT LOCK NOWAIT ;
ZSURYO にインデクスを定義する。
図 6-2-1 存在チェックの
SQL
例DB
の件数を考慮した記述© Hitachi, Ltd. 2013 , 2015. All rights reserved.
6-3 NOT (!=) の使用上の注意
60
NOT
(!=
)を使用した条件に対して、HiRDB
は、あまり絞り込めないと判断し結合方法、結合順序を決定します。取り得る値が1か0だけのフラグなど2値しか持たない列は、
条件に指定してもあまり絞り込めないので、
NOT
(!=
)を使用して条件を指定することで、HiRDB
は、絞り込めないことを認識できます。3値以上持つがあまり絞り込めない場合は、NOT IN
を用いても良いです。例を図 6-3-1に示します。Point
絞り込めないとわかっている条件はNOT
(!=
)を指定する○
~ FROM JUTYU JU,ZAIKO ZA WHERE JU.DNO = ZA.DNO AND JU.FLAG != 1 AND ZA.ZSURYO = 20×
~ FROM JUTYU JU,ZAIKO ZA WHERE JU.DNO = ZA.DNO AND JU.FLAG = 0AND ZA.ZSURYO = 20
JU.FLAGは、1か0であり、かつ ZA.ZSURYO=20が絞り込める場合
図 6-3-1 結合を伴う
SQL
でのNOT
使用例JU.FLAG != 1とすることで、
ZA.ZSURYO = 20のインデクスを
確実に使用し、ZA
からJU
へのネスト ループジョインにて高速に処理する。DB
の件数を考慮した記述© Hitachi, Ltd. 2013 , 2015. All rights reserved.
6-4 集合演算の使用上の注意(1)
61
UNION/UNION ALL
などの集合演算を使用したとき、集合演算で区切られた問合せ指定(
SELECT
文)は、別々に表アクセスします。また、集合演算を使用すると、作業表を作成することが多いです(
UNION ALL
のみの集合演算であれば集合演算のための作業表 は作成しない)。そのため、集合演算を用いないSQL
文にすると処理性能が向上すること が多いです。図 6-4-1に、単純な場合の例を示します。
Point
各問合せ指定の述語に指定する値だけが異なるような場合は、集合演算を使用しないようにする
○
SELECT SNAME FROM ZAIKOWHERE ZSURYO IN (10, 20) ;
×
SELECT SNAME FROM ZAIKOWHERE ZSURYO = 10 UNION
SELECT SNAME FROM ZAIKO
WHERE ZSURYO = 20 ;
=条件の値だけが異なる場合は、
UNION
等の集合演算を使用しない。図 6-4-1 集合演算を使用しないSQL文の例
IN
述語を使用することにより集合演 算を使用しない。DB
の件数を考慮した記述6-4 -1 集合演算の使用上の注意(2)
結合条件を
OR
論理演算すると、HiRDB
は、直積で処理します。直積では、全データの 突合せ処理を伴うため、集合演算に変形し、OR
論理演算を不要とすることで直積処理が 無くなり処理性能が向上することが多いです。例を図 6-4-2、6-4-3に示します。
Point
結合を伴うSQL
で、結合条件をOR
論理演算する必要がある場合は、集合演算 を使用する
○
SELECT ZA.NAMEFROM JUTYU JU, ZAIKO ZA WHERE JU.DNO = ZA.DNO UNION ALL
SELECT ZA.NAME
FROM JUTYU JU, ZAIKO ZA WHERE JU.ZNO = ZA.ZNO AND JU.DNO != ZA.DNO ;
×
SELECT ZA.NAMEFROM JUTYU JU, ZAIKO ZA WHERE (JU.DNO = ZA.DNO OR JU.ZNO = ZA.ZNO) ;
DISTINCT無し。結合条件をOR論理
演算している。図 6-4-2 直積を回避するためにUNION ALLを利用するSQL文の例
UNION ALL
を利用し、結合条件 のOR
をなくす。UNION ALL
で処理できるように 工夫する。DB
の件数を考慮した記述© Hitachi, Ltd. 2013 , 2015. All rights reserved.
6-4 -2 集合演算の使用上の注意(3)
63
○
SELECT ZA.NAMEFROM JUTYU JU, ZAIKO ZA WHERE JU.TCODE = 'A01' AND JU.DNO = ZA.DNO
UNION
SELECT ZA.NAME
FROM JUTYU JU, ZAIKO ZA WHERE JU.TCODE = 'A01'
AND JU.SURYO = ZA.ZSURYO ;
×
SELECT DISTINCT ZA.NAMEFROM JUTYU JU, ZAIKO ZA WHERE JU.TCODE = 'A01' AND (JU.DNO = ZA.DNO
OR JU.SURYO = ZA.ZSURYO) ;
DISTINCT指定有り。
結合条件を
OR
論理演算している。図 6-4-3 直積を回避するために
UNION
を利用するSQL
文の例UNIONを利用し、結合条件のOR
をなくす。UNION
では重複を排除するため、DISTINCTの指定が不要。
DB
の件数を考慮した記述6-5 DISTINCT の使用上の注意
DISTINCT
は重複排除のために作業表作成とソートを行います。そのオーバヘッドがあるので、必要のない
DISTINCT
は使用しないでください。重複排除が必要な場合でも、選択式が列指定のみで、かつ値の重複が多い場合は、GROUP BYを用いてください。例 を図 6-5-1に示します。
GROUP BY
を用いた場合、以下の向上が図れます。
インデクスが定義されていれば、インデクスを利用して、重複排除を効率よく行える。
インデクスを利用できなくても、グループ分け高速化機能*(SQL
最適化オプション)が適用できれば、処理性能が向上することが多い。
Point DISTINCT
は、確実に重複があり、重複を排除する必要がある場合以外使用しない
○
SELECT SNAME FROM ZAIKOGROUP BY SNAME ;
△
SELECT DISTINCT SNAME FROM ZAIKO ;不要なDISTINCTは使用しない。
図 6-5-1 重複排除を効率よく行うSQL文の例
選択式が列のみで、重複が多い場 合の重複排除は、GROUP BYを用 いる。
<補足事項>
GROUP BYを使用する場合、重複排除した結果の行数が1024(クライアント環境定義のPDAGGRデフォルト値)
を超えるならば、PDAGGRに1024より大きい値を指定すると処理性能が向上する場合があります。
* SQLのGROUP BY句を指定してグループ分け処理をする場合、ソートしてからグループ分けをしています。これにハッシングを組み合わせて グループ分けすることで高速なグループ分け処理が実現できます。
DB
の件数を考慮した記述© Hitachi, Ltd. 2013 , 2015. All rights reserved.
6-6 ビュー表の使用上の注意(1)
65
ビュー表定義に、
DISTINCT
、GROUP BY
、結合表を指定すると、内部導出表を作成す ることが多くなります(内部導出表の作成条件は、マニュアル「SQL
リファレンス」を参照)。ビュー表定義で内部導出表を作成した場合、以下のような点で性能が悪くなります。
内部導出表は、ビュー定義時の導出問合せ式の結果で作成する作業表であるため、作業表への
I/O
が発生する。
内部導出表を作成すると、ビュー表検索時に指定した探索条件は、内部導出表の作成後に評価するため、内部導出表作成時の処理件数が多くなり性能が悪くなる。
これらは、ビュー表だけでなく、WITH句を含めた名前つき導出表すべてに該当します。
例を図 6-6-1、6-6-2に示します。
Point
ビュー表定義でDISTINCT
指定、GROUP BY
指定は注意が必要ビュー表定義で結合表(LEFT OUTER JOIN/INNER JOIN)指定は注意が必要
DB
の件数を考慮した記述6-6 -1 ビュー表の使用上の注意(2)
○
CREATE VIEW V1(DNO, TCODE) AS SELECT DNO, TCODEFROM JUTYU ;
SELECT DISTINCT ZA.SNAME FROM V1 V, ZAIKO ZA
WHERE V.DNO = ZA.DNO AND V.TCODE = 'A' ;
×
CREATE VIEW V1(DNO,TCODE)AS SELECT DISTINCT DNO,TCODE FROM JUTYU ;
SELECT ZA.SNAME
FROM V1 V, ZAIKO ZA WHERE V.DNO = ZA.DNO AND V.TCODE = 'A' ;
DISTINCT
を指定すると内部導出表 となる。図 6-6-1 内部導出表とならないビュー表の例 その1
この条件はDISTINCT処理後に評価 する。
重複排除が必要な場合は
VIEW
の 外に記述する。内部導出表とならないため、この条 件はDISTINCT処理前に評価できる。
DB
の件数を考慮した記述© Hitachi, Ltd. 2013 , 2015. All rights reserved.
6-6 -2 ビュー表の使用上の注意(3)
67
○
CREATE VIEW V1(SCODE,TCODE) AS SELECT ZA.SCODE, JU.TCODE FROM JUTYU JU, ZAIKO ZA WHERE JU.DNO= ZA.DNO ; SELECT ZA2.SNAMEFROM V1 V, ZAIKO2 ZA2
WHERE V.SCODE = ZA2.SCODE AND V.TCODE = 'A' ;
×
CREATE VIEW V1(SCODE,TCODE) AS SELECT ZA.SCODE, JU.TCODEFROM JUTYU JU INNER JOIN ZAIKO ZA ON JU.DNO= ZA.DNO ;
SELECT ZA2.SNAME
FROM V1 V, ZAIKO2 ZA2
WHERE V.SCODE = ZA2.SCODE AND V.TCODE = 'A' ;
INNER JOIN
を指定すると内部導 出表となる場合がある。ビュー定義時のINNER JOIN処理 後に評価する。
ビュー定義では、INNER JOINを 使用しない。
内部導出表とならないため、ビュー 定義時の結合処理前に評価できる。
図 6-6-2 内部導出表とならないビュー表の例 その2