2017-09-25 9 views
2

パフォーマンスの問題が大きすぎます。私はDBからデータを取得し、別のテーブルに挿入するためにPHPスクリプトを使用しています(スクリプトはDB上のクエリを実行します、後でデータを取得するために貼り付けたものと、INSERT)。結果を結合して出力する必要がある2つのテーブルがあります(3番目のテーブルを記入してください)が、そのテーブルの1つには3.9Mのデータ行があり、2番目のテーブルには416kの行があります。問題は、テーブルが何らかの方法で(カラム "name"を介して)結合されていないので、タイプvarcharでの結合を使用しなければならないことです。大きなテーブルでのMySQLクエリのパフォーマンスの問題

TABLE streets 
    id (PK, int), 
    name varchar(70), 
    postnrid (FK, int) 

    TABLE csvstreets 
    id (PK, int), 
    lat decimal(12,10), 
    lng decimal(12,10), 
    streetname varchar(70) 

表の通りは390万行の一つであり、クエリは次のようになります:

SELECT s.id, c.lat, c.lng FROM streets AS s JOIN csvstreets AS c ON LOWER(s.name) = LOWER(c.streetname) 

「問合せはストレート2日間走っていた、そしてそれはdidnのテーブル構造は、このようなものです私はそれをキャンセルしなければならなかった。私は両方のテーブルの両方の "名前"列を索引付けしました。クエリにEXPLAINを行う上では、この出力:

# id, select_type, table, type, possible_keys, key, key_len, ref, rows, Extra 
'1', 'SIMPLE', 'c', 'ALL', NULL, NULL, NULL, NULL, '416240', '' 
'1', 'SIMPLE', 's', 'index', NULL, 'name', '73', NULL, '3890226', 'Using where; Using index; Using join buffer (flat, BNL join)' 

「csvstreets」テーブルは、私はそれのために作ったインデックスを使用していないように見えます。 varchar結合のパフォーマンスを向上させるために私が見つけたすべてを試してきたので、私は助言を使うことができました。 また、返されるすべてのデータ(約380k)が必要なので、結果の出力を制限することはできません。 スクリプト内にechoを追加して、どこで停止しているかを確認しましたが、のクエリを2日間実行していただけで、INSERT部分には届きませんでした。

+2

私がインデックスされている*両方の「名前」列:あなたのクエリがまだ完了していないことをした後、すべての出力を表示する場合は

s.name) 'また、クエリの計画を説明してください –

+0

情報のおかげで、"名前 "の列はキャプションのサイズが異なります。たとえば、1つの通りは" Balsta 300 "、もう1つは" balsta 301 "です。 – MirzaS

+4

あなたが提出した照合が_cs(大文字小文字の区別があります)またはバイナリで終わらない限り、lower()またはupper()を使う必要はありません(LOWER()またはUPPER()w/e、 – user1844933

答えて

0

lower()を削除します。あなたのインデックスを使用して結合を維持しているので、大文字と小文字を区別する照合順序を設定しない限り、必要はありません。確かに "Balsta 300"と "Balsta 301"を区別する必要はありません。 (*その有用な任意の多くの原因ではないLOWER `に両方のテーブルの上に

show create table streets 
show create table csvstreets 
explain SELECT s.id, c.lat, c.lng FROM streets AS s JOIN csvstreets AS c ON s.name=c.streetname 
関連する問題