20120721 tuning slide_share
description
Transcript of 20120721 tuning slide_share
こんなSQL性能改善策もあります
~ Oracle Database 11g バーチャル・カラム 活用 ~
JPOUG 「JPOUG> SET EVENTS 20120721」 アンカンファレンス資料 宇多津 真彦 2012年07月21日
• 本資料はあくまで個人の見解に基づいて記述したものであり、所属する会社・団体とは一切関係ありません。
2
はじめに
• 今日お話する内容は、ある特定の状況でしか使えないSQL性能改善であり、かつ、標題に「バーチャル・カラム」とあるように、テーブルのカラム構造の変更まで視野に いれた話ですが、工夫次第でおもしろいことができる、 ということをお話します
• Oracle Database 11gの基本機能に関する話ですが、 これを機会にいろんな機能に興味をもっていただけると 嬉しいです • まずは、「新機能マニュアル」を熟読ください
3
お客様のある悩み
4
「SQLの処理で遅いものがある」
•受注表から請求対象データを抽出する処理 お客様
•受注表(履歴を持つ) → データ件数が多い
•請求対象データを抽出 → 過去データの大半は請求済 (二重請求なし)
•「パーティショニングしてますか?」
•「請求対象は日付である程度区切れますか? もし区切れるとするならば、期間はどれくらいになりますか?」
•「請求済みをフラグで管理していますか?」
想定できること
相談内容
お客様への質問
お客様からの状況説明
5
「パーティションは使ってるよ」
「未請求データは受注テーブルのほんの一部なんだけど、過去データを全件みにいってるみたいなんだよね」
「うち(お客様企業)が扱っているのは日用品じゃないから、受注から請求までの期間が長いんだよ。だから日付で区切れないんだよね」
「請求対象は請求日が入ってないもの、かな」
お客様
•日付で区切れなければパーティションも効果が得られない
• IS NULL検索では対象データが少なくても索引は使われ ないので全件検索になってしまう
回答内容
想定されるSQLの処理
• パーティショニングが効果的な問い合わせ
• 「受注日」カラムで条件指定できなければ、「未請求フラグ」 カラムを追加してデータを絞り込むしかない • 幸い、大半のデータは請求済み
• 「未請求フラグ」に索引を作成すれば効果的にデータ絞り込みができる
6
SELECT * FROM 受注表
WHERE 受注日 >= TO_DATE('2012/07/01','YYYY/MM/DD')
AND 受注日 < TO_DATE('2012/07/31','YYYY/MM/DD')+1
AND 請求日 IS NULL ; -- 未請求
SELECT * FROM 受注表
WHERE 未請求フラグ = '1' ; -- 未請求
パーティション・キー
IS NULL検索でも、 パーティションで十分に
絞り込みができれば 問題なし
「未請求フラグ」カラムを追加する?
• 「未請求フラグ」カラム追加懸念点 • 「受注表」に「未請求フラグ」カラムを追加。当カラムに索引作成
• 物理的に領域を使用(表、索引ともに)
• 問題となっているSQL以外のアプリケーションに変更が発生
• 「請求日」カラムに日付がセットされると、「未請求フラグ」カラム を請求を示す値('0'などに)更新する処理を追加
• アップデート・トリガーで更新?
• 行儀の悪いSQLの修正
7
SELECT * FROM 受注表 ..
INSERT INTO 受注表 VALUES (:id, :dt ..
*の使用
カラム指定なし
バーチャル・カラム機能を使ってみる
• Oracle Database 11gからの標準機能
• 実データは持たず、他のカラムから関数によって定義される仮想的な列 • ディスク上に格納されない列
• 他のカラムから導出されるカラムの為、更新できない
• 索引付けが可能であり、統計を収集できる
• 「受注表」にバーチャル・カラムを適用したイメージ
8
id 受注日 請求日 未請求フラグ
1 2012/06/21 2012/07/21 NULL
2 2012/06/21 2012/07/21 NULL
3 2012/07/21 NULL '1'
4 2012/07/21 NULL '1'
バーチャル・カラム作成
索引作成
検索対象外の値を NULLにすることで 索引のサイズを 小さくできます
テストを実施してみる(その1)
• テストデータ: 180万行(1,000件/日 × 30日×12月×5年) • うち、1ヶ月分(30,000行)を抽出対象とする(1/60)
• 1行あたり500Byte • 500Byte × 1,800,000 = 900,000,000 なので、1GB程度のデータ量
• カラム構成
9
CREATE TABLE test01 (
id NUMBER(8) CONSTRAINT PK_test01 PRIMARY KEY,
dt01 DATE, -- 受注日相当
dt02 DATE, -- 請求日相当
dummy CHAR(482)
)TABLESPACE test;
まずは非パーティション表で確認
extent 5MB単位
テストを実施してみる(その2)
• テストデータ投入後、バーチャル・カラム作成
• 索引作成
• テストデータ確認
10
ALTER TABLE test01 ADD (
vflg01 VARCHAR2(1) AS (DECODE(dt02,NULL,'1','0')),
vflg02 VARCHAR2(1) AS (DECODE(dt02,NULL,'1',NULL))
);
CREATE INDEX test01_vflg01 ON test01(vflg01)TABLESPACE users;
CREATE INDEX test01_vflg02 ON test01(vflg02)TABLESPACE users;
索引のサイズ比較
extent 64KB単位
NULL
テストを実施してみる(その3)
• セグメントのサイズ比較
• アクセスパス比較 • 以下の3種類で比較(次ページ以降)
11
SELECT MAX(dt01) FROM test01 WHERE dt02 IS NULL;
SELECT MAX(dt01) FROM test01 WHERE vflg01 = '1';
SELECT MAX(dt01) FROM test01 WHERE vflg02 = '1';
(1)
(2)
(3)
テストを実施してみる(その4) SQL*Plusのset autotraceの表示
(1)
(2)
(3)
12
ヒストグラム未取得 ヒントで索引指定
ヒストグラム取得 ヒント指定無し
もう少し複雑なバーチャル・カラム(その1)
• 抽出条件を追加 • 「出荷日」に日付がセットされていて、
かつ「請求日」に日付がセットされていない
• 「受注表」にバーチャル・カラムを適用したイメージ
13
SELECT * FROM 受注表
WHERE 出荷日 IS NOT NULL
AND 請求日 IS NULL ; -- 未請求
id 受注日 出荷日 請求日 請求対象フラグ
1 2012/06/21 2012/07/05 2012/07/21 NULL
2 2012/06/21 2012/07/05 2012/07/21 NULL
3 2012/07/21 2012/07/21 NULL '1'
4 2012/07/21 NULL NULL NULL
バーチャル・カラム作成
索引作成
検索対象外の値を NULLにすることで 索引のサイズを 小さくできます
もう少し複雑なバーチャル・カラム(その2)
• 実装イメージ
14
CREATE TABLE test02 (
id NUMBER(8)
CONSTRAINT PK_test02 PRIMARY KEY,
dt01 DATE, -- 受注日相当
dt02 DATE, -- 出荷日相当
dt03 DATE, -- 請求日相当
dummy CHAR(475)
)TABLESPACE test;
ALTER TABLE test02 ADD (
vflg01 VARCHAR2(1) AS (
DECODE(dt02,NULL,NULL,
DECODE(dt03,NULL,'1',NULL)
)
)
);
SELECT MAX(dt01)
FROM test02
WHERE DT02 IS NOT NULL
AND DT03 IS NULL;
SELECT MAX(dt01)
FROM test02
WHERE vflg01 = '1';
検索対象
パーティショニング+遅延セグメント作成との 組合せを試してみる(その1)
• 遅延セグメント作成機能 • Oracle Database 11g R2からのEnterprise Edition機能
• パーティショニングとの組合せは11.2.0.2以降より可能
• Oracle Database 11g R1より提供している時間隔パーティション (インターバル・パーティション)が使えない場合でも利用可能
例)参照パーティション(リファレンス・パーティション) パーティション・キーがDATE型、NUMBER型以外
• あらかじめ、想定されるパーティションを作成しておいてもよい
例) 25年分のパーティションをあらかじめ作成しておく、など
15
パーティショニング+遅延セグメント作成との 組合せを試してみる(その2)
16
データ・ローディング 対象
初期エクステントは 確保される
まとめ
• Oracle Database 11g からの基本機能「バーチャル・カラム」を利用した性能改善案についてお話しました
• また、パーティショニングと遅延セグメント作成(EE機能)の組合せについてもご紹介しました
• 新しいバージョンの新機能をいろんなところに適用して みてください • 古いバージョンを使っているところは早々にバージョンアップを
ご検討ください!
17