2012-03-01 15 views
2

私は3つのテーブルを持つデータベースを持っており、第1のテーブルを他の2つのテーブルとクロスリファレンスする必要があります。すべてのテーブルには共通の1つのフィールドがあり、これはMSISDN(モバイル/携帯電話番号)で、少なくとも10桁の長さです。MySQLクエリー時間を短縮する(現在は24時間稼働していますが、まだ稼働しています)

表1 - 819248行

表2 - 75308813行

表3 - 17701196行

私は表1からすべての行を返すと、表2から、いくつかのフィールドを追加したい

一致するMSISDNがある場合は表3を参照してください。 私のクエリは現在24時間以上実行されており、このようなものがどれくらいの時間かかるかを知る方法はありません。

このタイプのクエリは通常のプロジェクトである可能性があります。クエリ時間を大幅に短縮する方法はありますか?

私はMSISDNと返す必要があるフィールドでインデックステーブル2と3を持っています。

私のクエリは、このようなものです:

create TABLE FinishedData 
select 
    Table1.ADDRESS, table1.POSTAL, table1.MOBILE, 
    table1.FIRST, table1.LAST, table1.MID, table1.CARRIER, 
    table1.TOWN, table1.ID, table2.status as 'status1', 
    table2.CurrentNetworkName as 'currentnetwork1', 
    table2.DateChecked as 'datechecked1', table3.Status as 'status2', 
    table3.CurrentNetworkName 'currentnetwork2', 
    table3.DateChecked as 'datechecked2' 
from 
    table1 left join (table2, table3) 
     on (right(table1.MOBILE, 10) = right(table2.MSISDN, 10) 
     AND right(table1.MOBILE,10) = right(table3.MSISDN,10)) 

MySQLが12ギガバイトのメモリと3GHzの@ 8つの論理コアを持つ64ビットのWindowsマシン上で実行されています。 MySQLdはクエリ実行時に10%のCPUと600MBのリソースしか使用していません。

何か助けていただければ幸いです。

答えて

3

右の関数では、パフォーマンスの問題が発生しますこの関数を使用すると、MySQLはインデックスを使用できません。

私のお勧めは、次のとおりです。

  1. はMSISDN
  2. reverse内容を表2と表3の新しいフィールドを作成し、左関数で右の機能を置き換えるに参加してください。

この小さな変更で、MySQLはインデックスを作成して結合を行うことができます。

は手順について説明した:

1)新しい列を作成します。

Alter table table2 add column r_MSISDN varchar(200); 
update table2 set r_MSISDN = reverse(MSISDN); 

Alter table table3 add column r_MSISDN varchar(200); 
update table3 set r_MSISDN = reverse(MSISDN); 

2)新規加入:

... 
from 
    table1 left join (table2, table3) 
     on (right(table1.MOBILE, 10) = left(table2.r_MSISDN, 10) 
     AND right(table1.MOBILE,10) = left(table3.r_MSISDN,10)) 
+0

ありがとうdanihp - 確かに問題を引き起こしている「正しい」機能のようです。私はあなたの記事から、「左」に同じ問題はないと思います。正規化されたデータを含む新しい列を作成してから、「右」または「左」を使用しないようにします。これにより、今後さらにデータを逆にしなければなりません。新しい列を作成するためにコードを使用していますが、データを元に戻す代わりに正規化しています。 –

1

RIGHT機能です。 where節の関数を使うということは、比較する前に各行の関数が返す値を計算しなければならないため、MySQL(とおそらくすべてのデータベース)がインデックスを使用できないことを意味します。

このクエリを高速化する場合は、MSISDNを正規化された形式で保存し、=演算子を使用して比較することを検討してください。

MSISDNの番号がわかりません。固定幅の数字なら、あなたの仕事は簡単です。セパレータ(スペース/ハイフン)が含まれていて、セパレータが読みやすくするために存在する場合は、データベースに格納する前にセパレータを削除する必要があります。最初の10文字が重要で残りがオプションの場合は、最初の10文字と残りの文字を別々の列に格納することを検討します。

+0

ありがとうSalman。私はdanihpによって提案されたコードを使用して新しい列を作成していますが、データを元に戻す代わりに正規化しています。とにかくこれを元にしておくべきだったと思うので、これは私が使う解決策です。これは、将来的にはより多くのMSISDNを正規化してこれらに対して照会できることを意味します。 –

1

すでに述べたように、問題はインデックスを使用できないright関数で問題になります。

簡単に言えば、table1の各行の現在のクエリはtable2のフルスキャンを行い、一致するたびにtable3のフルスキャンを行います。 table2とtable3にある行の数を考慮すると、クエリが終了する前に世界を見ることができます。

もう1つの問題は、MySQLが考えるように、クエリが膨大なトランザクションを開始し、ロールバックされ、分離レベルを考えるかもしれないということです。

私は現在のテーブルを変更しません。必要な列を持つtable2とtable3のサブコピーを作成し、table2コピー(table3コピーのright(table3.MSISDN、10))に別のインデックス付き列として右側(table2.MSISDN、10)を追加します。

次に、コピーを使用してLEFT JOINを実行するか、または表1のいずれかと一致する行へのコピーを減らしてLEFT JOINを実行できます。

+0

ヘルプnewtoverありがとうございます。あなたが投稿した前に私は新しい列を作成し始めましたので、これを完成させ、それが機能することを確認します。将来私はtable2とtable3を再度参照しているかもしれないので、別の列が必要なので、毎回新しいテーブルを作成しないようにします。あなたの回答を投票するのに十分な担当者がいません - 申し訳ありません!私は15人以上必要です。 –

関連する問題