16

テーブル名を除いて同じ構造のテーブルが 10 個あります。

次のように定義されたsp(ストアドプロシージャ)があります:

 select * from table1 where (@param1 IS NULL OR col1=@param1)
 UNION ALL
 select * from table2 where (@param1 IS NULL OR col1=@param1)
 UNION ALL
 ...
 ...
 UNION ALL
 select * from table10 where (@param1 IS NULL OR col1=@param1)

次の行でspを呼び出しています:

call mySP('test')  //it executes in 6,836s

次に、新しい標準クエリ ウィンドウを開きました。上記のクエリをコピーしただけです。次に、@param1 を「test」に置き換えました。

これは 0,321 秒で実行され、ストアド プロシージャよりも約 20 倍高速です。

結果がキャッシュされないように、パラメーター値を繰り返し変更しました。しかし、これは結果を変えませんでした。SP は、同等の標準クエリよりも約 20 倍遅くなります。

なぜこれが起こっているのかを理解するのを手伝ってもらえますか?

誰かが同様の問題に遭遇しましたか?

Windows Server 2008 R2 64 ビットで mySQL 5.0.51 を使用しています。

編集: テストに Navicat を使用しています。

どんなアイデアも私にとって役に立ちます。

EDIT1:

Barmarの回答に従って、いくつかのテストを行ったところです。

最後に、以下のようにspを1行だけ変更しました:

 SELECT * FROM table1 WHERE col1=@param1 AND col2=@param2

次に、最初に標準クエリを実行しました

 SELECT * FROM table1 WHERE col1='test' AND col2='test'  //Executed in 0.020s

私が私のSPを呼んだ後:

 CALL MySp('test','test')    //Executed in 0.466s

そのため、where句を完全に変更しましたが、何も変更されていません。そして、navicat の代わりに mysql コマンド ウィンドウから sp を呼び出しました。それは同じ結果をもたらしました。私はまだそれにこだわっています。

私のsp ddl:

 CREATE DEFINER = `myDbName`@`%`
 PROCEDURE `MySP` (param1 VARCHAR(100), param2 VARCHAR(100))
 BEGIN
    SELECT * FROM table1 WHERE col1=param1 AND col2=param2
 END

また、col1 と col2 は結合されて索引付けされます。

では、なぜ標準クエリを使用しないのですか? 私のソフトウェア設計はこれには適していません。ストアド プロシージャを使用する必要があります。ですから、この問題は私にとって非常に重要です。

EDIT2:

クエリ プロファイル情報を取得しました。大きな違いは、SPプロファイル情報の「送信データ行」によるものです。データ部分の送信には、クエリ実行時間の %99 がかかります。ローカル データベース サーバーでテストを行っています。リモートコンピューターから接続していません。

SP プロファイル情報 SP プロファイル情報

プロファイル情報のクエリ ここに画像の説明を入力

私は自分のspで以下のような強制インデックスステートメントを試しました. でも同じ結果。

 SELECT * FROM table1 FORCE INDEX (col1_col2_combined_index) WHERE col1=@param1 AND col2=@param2

以下のようにspを変更しました。

 EXPLAIN SELECT * FROM table1 FORCE INDEX (col1_col2_combined_index) WHERE col1=param1 AND col2=param2

これにより、次の結果が得られました。

 id:1
 select_type=SIMPLE
 table:table1
 type=ref
 possible_keys:NULL
 key:NULL
 key_len:NULL
 ref:NULL
 rows:292004
 Extra:Using where

次に、以下のクエリを実行しました。

 EXPLAIN SELECT * FROM table1 WHERE col1='test' AND col2='test'

結果は次のとおりです。

 id:1
 select_type=SIMPLE
 table:table1
 type=ref
 possible_keys:col1_co2_combined_index
 key:col1_co2_combined_index
 key_len:76
 ref:const,const
 rows:292004
 Extra:Using where

SP で FORCE INDEX ステートメントを使用しています。しかし、それはインデックスを使用しないことを主張しています。何か案が?私は終わりに近づいていると思います:)

4

4 に答える 4

8

Possible character set issue? If your table character set is different from your database character set, this may be causing a problem.

See this bug report: http://bugs.mysql.com/bug.php?id=26224

[12 Nov 2007 21:32] Mark Kubacki Still no luck with 5.1.22_rc - keys are ingored, query takes within a procedure 36 seconds and outside 0.12s.

[12 Nov 2007 22:30] Mark Kubacki After having changed charsets to UTF-8 (especially for the two used), which is used for the connection anyways, keys are taken into account within the stored procedure!

The question I cannot answer is: Why does the optimizer treat charset conversions an other way within and outside stored procedures? (Indeed, I might be wrong asking this.)

于 2013-06-05T20:49:22.110 に答える
0

私はストアド プロシージャを使用するのが好きなので、興味深い質問です。理由はメンテナンスとカプセル化の原則です。

これは私が見つけた情報です: http://dev.mysql.com/doc/refman/5.1/en/query-cache-operation.html

クエリ キャッシュは、1. 外部クエリに属する​​サブクエリであり、2. ストアド プロシージャ、トリガー、またはイベントの本体内で実行されるクエリには使用されないと述べています。

これは、設計どおりに機能することを意味します。

于 2013-06-05T20:10:51.967 に答える