4

そこで、MySQL コンソールで以下を実行して、クエリの速度を妨げているものを確認するためのコントロール テストを行いました。

SELECT bbva_deductions.ded_code, SUBSTRING_INDEX(bbva_deductions.employee_id, '-' , -1) AS tt_emplid, 
            bbva_job.paygroup, bbva_job.file_nbr, bbva_deductions.ded_amount 
            FROM bbva_deductions 
            LEFT JOIN bbva_job 
            ON CAST(SUBSTRING_INDEX(bbva_deductions.employee_id, '-' , -1) AS UNSIGNED) = bbva_job.emplid LIMIT 500

実行には一貫して約 4 秒かかりました。(500行だけでは非常に高いようです)。

結合の CAST 部分を削除するだけで、0.01 秒に短縮されました...

いったいなぜCASTさんはこんなに遅いのでしょう?ここでMySQLの神々を怒らせるようなことをしていますか?

編集:

ここで要求されているのは、EXPLAIN 出力です。

ここに画像の説明を入力

そしてキャストなし:

ここに画像の説明を入力

拡張説明:

ここに画像の説明を入力

4

1 に答える 1

6

How MySQL Uses Indexesに記載されているとおり:

MySQL は次の操作にインデックスを使用します。

デレティア
  • 結合を実行するときに、他のテーブルから行を取得するため。列が同じタイプおよびサイズとして宣言されている場合、MySQL は列のインデックスをより効率的に使用できます。このコンテキストでは、VARCHARCHARは、同じサイズとして宣言されている場合、同じと見なされます。たとえば、VARCHAR(10)CHAR(10)は同じサイズですが、VARCHAR(10)CHAR(15)は異なります。

    変換せずに値を直接比較できない場合、類似していない列を比較すると、インデックスを使用できない場合があります。数値列を文字列列と比較するとします。数値列などの特定の値は、 、、、1などの文字列列の任意の数の値と等しい場合があります。これにより、文字列列のインデックスの使用が除外されます。'1'' 1''00001''01.e1'

あなたの場合、(あるテーブルの文字列列の) 部分文字列と別のテーブルの文字列列の比較で結合しようとしています。この操作にはインデックスを使用できますが、比較は辞書式に実行されます (つまり、オペランドが数値を表している場合でも、オペランドを文字列として扱います)。

一方の側を明示的に整数にキャストすることにより、(必要に応じて) 数値的に比較が実行されますが、これには MySQL が文字列列の型を暗黙的に変換する必要があるため、その列のインデックスを使用できません。

スキーマの設計が不十分なため、この障害にぶつかりました。すべての列が次のようになるように努力する必要があります。

  1. コンテンツに最も関連するデータ型を使用してエンコードされます。と

  2. 単一の情報のみを含む -データベース列に区切られたリストを保存するのは本当に悪いことですか? を参照してください。

少なくとも、あなたbbva_job.emplidは整数でなければなりません。そして、bbva_deductions.employee_idその部分が別々の(適切に型指定された)列に格納されるように分割する必要があります。適切なインデックスを使用すると、クエリのパフォーマンスが大幅に向上します。

于 2013-07-24T06:18:06.287 に答える