- PR -

9iと10gの処理時間の差について

投稿者投稿内容
隣の古柴
ベテラン
会議室デビュー日: 2004/06/04
投稿数: 94
投稿日時: 2007-05-23 16:03
こんにちは。いつも勉強させていただいています。

とあるSELECT文を発行した際、社内の同じネットワーク上に接続されている
Oracleの9iと10gで処理時間に差が出ました。
9iでは瞬時に処理が行われるのに対し10gでは数秒かかります。
理由がSELECT文の書き方にあるとしたらと後学のためにご教示頂ければと書
き込みさせていただきました。

環境は、Oracle Database 9iと10g
アプリケーションはVB6で作成(oo4o)しています。
CreateDynaset()でSELECT文を発行するものです。


問題のSELECT文は下記の稚拙なものです(すみません)。
YMDはインデックスです。
NAME、BUNRUI1、BUNRUI2はすべてCHARでNOT NULLです。

SELECT
S11.CNT SCNT11, S12.CNT SCNT12, S13.CNT SCNT13, S14.CNT SCNT14, S15.CNT SCNT15, S16.CNT SCNT16, S17.CNT SCNT17
FROM
(SELECT COUNT(NAME) CNT FROM TBL
WHERE ( YMD >= '20060101' AND YMD <= '20061231' )
AND BUNRUI1 = '01'
AND BUNRUI2 = '01') S11,
(SELECT COUNT(NAME) CNT FROM TBL
WHERE ( YMD >= '20060101' AND YMD <= '20061231' )
AND BUNRUI1 = '01'
AND BUNRUI2 = '02') S12,
(SELECT COUNT(NAME) CNT FROM TBL
WHERE ( YMD >= '20060101' AND YMD <= '20061231' )
AND BUNRUI1 = '01'
AND BUNRUI2 = '03') S13,
(SELECT COUNT(NAME) CNT FROM TBL
WHERE ( YMD >= '20060101' AND YMD <= '20061231' )
AND BUNRUI1 = '01'
AND BUNRUI2 = '04') S14,
(SELECT COUNT(NAME) CNT FROM TBL
WHERE ( YMD >= '20060101' AND YMD <= '20061231' )
AND BUNRUI1 = '01'
AND BUNRUI2 = '05') S15,
(SELECT COUNT(NAME) CNT FROM TBL
WHERE ( YMD >= '20060101' AND YMD <= '20061231' )
AND BUNRUI1 = '01'
AND BUNRUI2 = '06') S16,
(SELECT COUNT(NAME) CNT FROM TBL
WHERE ( YMD >= '20060101' AND YMD <= '20061231' )
AND BUNRUI1 = '01'
AND BUNRUI2 = '07') S17

データとしては9iも10gも全く同じデータです。
よろしくお願い致します。
ラフィン
ぬし
会議室デビュー日: 2002/05/23
投稿数: 809
お住まい・勤務地: 外野
投稿日時: 2007-05-23 16:29
 サーバースペックは同等なんですよね?

 その程度のSQLでしたらSELECT文の書き方を疑うより、キャッシュやオプティマイザーに注目した方が早いかも。
隣の古柴
ベテラン
会議室デビュー日: 2004/06/04
投稿数: 94
投稿日時: 2007-05-23 17:43
レスありがとうございます。

>サーバースペックは同等なんですよね?

9iがPENV1.2G
10gがPEN4 3G(DUAL)

だったりします。

>その程度のSQLでしたらSELECT文の書き方を疑うより、キャッシュやオプティマイザーに注目した方が早いかも。

キャッシュですか。。。
正直その方面明るくはないのですが、大変ありがたく手がかりにさせて頂きます。
ラフィン
ぬし
会議室デビュー日: 2002/05/23
投稿数: 809
お住まい・勤務地: 外野
投稿日時: 2007-05-23 23:42
引用:

隣の古柴さんの書き込み (2007-05-23 17:43) より:

キャッシュですか。。。
正直その方面明るくはないのですが、大変ありがたく手がかりにさせて頂きます。


 同じSQLを2回実行してそれぞれの時間を計る。これを2つのサーバーでやってみると何か面白い結果がでるかも?

 やはり差が出るようでしたら、全件対象で同じことをやってみる。
SELECT COUNT(NAME) CNT FROM TBL

 これでも同様ならSQLの問題じゃないですよね?

 ここで逆転するならインデックスを使って同じことをやってみる。
SELECT COUNT(NAME) CNT FROM TBL
WHERE YMD >= '20060101' AND YMD <= '20061231'


 案外 SELECT SYSDATE FROM DUAL でも同等の差が出たりして(笑)
隣の古柴
ベテラン
会議室デビュー日: 2004/06/04
投稿数: 94
投稿日時: 2007-05-24 14:36
ラフィンさん、レスありがとうございます。

> 同じSQLを2回実行してそれぞれの時間を計る。これを2つのサーバーでやってみると何か面白い結果がでるかも?
>(以下略させて頂きました)

試してみました。
CreateDynaset()でSELECT文を発行したまま返答がない状態になります。
うーむ。。。
もしもし
ぬし
会議室デビュー日: 2004/10/15
投稿数: 280
投稿日時: 2007-05-24 14:56
バインド変数も使って無さそうな SQL なので、 SQL*Plus から実行して
SQL トレースを取れないか、とおもいますがどうでしょう。
(単なる SQL_TRACE = true より event 10046 level 8 で採取した方がいい)

せっかく索引があるのに、データが同じでも統計情報が実情にあって無くて
全件検索しまくってるとか。

# ただ、YMD のデータ型が不明ですが DATE 型だったら
# 暗黙変換しまくりそうな書き方ですね。

_________________
もしもし@RMAN 友の会
ラフィン
ぬし
会議室デビュー日: 2002/05/23
投稿数: 809
お住まい・勤務地: 外野
投稿日時: 2007-05-25 10:28
>もしもしさん

引用:

単なる SQL_TRACE = true より event 10046 level 8 で採取


 なるほど、こういうのがあったんですね。勉強になりました。

 私は
 alter session set sql_trace=true;
 alter session set timed_statistics=true;
 set autotrace on;
 の3本セットから tkprof をやっていました。

 実行プランの確認だけならツールで行いますけど。

>隣の古柴さん

 SQLがそれでいいのかははなはだ疑問ですが、実際に何が起こっているのかを調べることが大切かと思います。ハード環境、Oracleのバージョンや設定、テーブルの構造やデータ、全てが同じであっても同じSQLに対してDBMSが同じ挙動をするとは限りません。
もしもし
ぬし
会議室デビュー日: 2004/10/15
投稿数: 280
投稿日時: 2007-05-25 10:39
event 10046 の説明はここにあります。実行計画だけじゃなくて待機イベントも確認できるので、大抵は level 8 で取ってます。


_________________
もしもし@RMAN 友の会

[ メッセージ編集済み 編集者: もしもし 編集日時 2007-05-25 10:40 ]

スキルアップ/キャリアアップ(JOB@IT)