2016-05-10 5 views
0

私は顧客が1つのアドレスを持つことを許可しているので、左の結合を使用して 'customer'、 'customer_address'および 'country'の3つのテーブルを結合しています。 現在、13k +のお客様がおり、クエリには約40秒かかります。私は内部結合を試みましたが、その場合、私はアドレスのない顧客を得ていません。 'ON'のすべての列にインデックスが作成されますが、大きな違いはありません。 ここに私のクエリです:任意の助けをいただければ幸いです左の結合が2つしかない非常に遅いSQLクエリ

SELECT DISTINCT *, 
CASE 
    WHEN customer_address.customerid is NULL THEN customer.customerid 
    ELSE customer_address.customerid 
    END as customerid, 
CASE 
    WHEN address1 = '' THEN 'NA' 
    ELSE address1 
    END as address1 
FROM customer 
LEFT JOIN customer_address ON customer.customerid = customer_address.customerid 
LEFT JOIN country ON country.id = customer_address.country 
WHERE deleted='0' 
ORDER BY customer.customerid 
DESC 
LIMIT 0, 10 

EDIT:

ここ

3つのテーブルのために '説明' されています

顧客

Field  Type   Null Key Default Extra 
customerid int(12)  NO PRI NULL  auto_increment 
forename  varchar(128) YES  NULL  
surname  varchar(128) YES  NULL  
company  varchar(64) YES  NULL  
tel   varchar(32) YES  NULL  
tel2   varchar(32) YES  NULL  
fax   varchar(32) YES  NULL  
mob   varchar(32) YES  NULL  
email  varchar(255) YES  NULL  
date_reg  date   YES  NULL  
last_update datetime  YES  NULL  
deleted  int   NO  

customer_address

Field  Type   Null Key Default  Extra 
addressid varchar(12) NO PRI   
customerid varchar(12) YES MUL NULL  
address1  varchar(128) YES  NULL  
address2  varchar(128) YES  NULL  
town   varchar(128) YES  NULL  
county  varchar(128) YES MUL NULL  
postcode  varchar(12) YES  NULL  
country  int(12)  YES  NULL  
address_date datetime  YES  NULL  
isprimary int   NO not  

Field  Type   Null Key Default  Extra  
id   int(12)  NO PRI 0  
country  varchar(255) YES  NULL 

現時点では何も削除= '0'

EDIT 2はありません!

クエリ説明:

id select_type table    partitions type possible_keys key  key_len ref        rows filtered Extra  
1 SIMPLE  customer   NULL  ALL  deleted  NULL  NULL  NULL        13082 99.98  Using where; Using temporary; Using filesort 
1 SIMPLE  customer_address NULL  ALL  NULL   NULL  NULL  NULL        9983 100.00  Using where; Using join buffer (Block Nested Loop) 
1 SIMPLE  country   NULL  eq_ref PRIMARY,id  PRIMARY 4  db_name.customer_address.country  1 100.00  NULL 

はEDIT 3:

1 SIMPLE customer NULL index NULL customerid 4 NULL 1 10.00 Using where; Using temporary 
1 SIMPLE customer_address NULL ALL  NULL NULL NULL NULL 9983 100.00 Using where 
1 SIMPLE country  NULL eq_ref PRIMARY,id PRIMARY  4 db_name.customer_address.country 1 100.00 NULL 
+0

インデックスに 'deleted'カラムがありますか? – mitkosoft

+0

これらのケースは本当に必要ですか?それらを取り除き、どれくらいの時間がかかるかを確認してください – Matt

+0

Distinct、Case-Then-Elseのどちらも使用しないとパフォーマンスはどのようになりますか? – xarmengol

答えて

0

これを試すことができます。 CustomerIdをNULLとして受け取らないため、最初のCASE文を使用する必要はありません。私はそれがクエリもパフォーマンスを向上させると仮定していますあまりにとしてORDER BY句を削除した(CustomerIdのレコードが物理的にデータベースに配置されている方法を示して主キーです。デフォルトの並び順は昇順です。)

SELECT DISTINCT *, C.customerid as customerid, 
CASE 
     WHEN customer_address.address1 = '' THEN 'NA' 
     ELSE customer_address.address1 
     END as address1 from (select * 
    FROM customer where deleted='0' order by customerid DESC) AS C 
    LEFT JOIN customer_address ON C.customerid = customer_address.customerid 
    LEFT JOIN country ON country.id = customer_address.country 
    LIMIT 0, 10 
+0

良い点は、パフォーマンスにまだ影響しません。ありがとうございます – Genov

+0

あなたは今確認できますか? –

+0

このようにパフォーマンスが向上し、問題がどこから発生したのかをローカライズしています。基本的にORDER BYはそれを遅くします。私を鉱山から取り除くと、0.02秒になる。任意の提案 – Genov

0

さて、あなたは索引を使用しないすべてのタイプの問合せが必要です。そのうちの1つには恐ろしいファイルがありますが、これは非常に高価な操作です。

  1. customer_address.customeridフィールドにインデックスを追加します。これは、customer_addressテーブルからメインの顧客テーブルへのレコードの照合に使用されます。

  2. クエリから返す列をリストします。*は使用しないでください。たとえば、顧客とアドレステーブルの両方からcustomeridを返す必要がある理由はわかりません。

  3. 第1番目のケースステートメントを取り除く。 customer.customeridフィールドには常に値が入力されます。

  4. MySQLはソートに得意先のインデックスを使用することについて考えさせるために、顧客テーブルの後にインデックスヒントを追加します。

    ... FROM customer FORCE INDEX index_name_forcustomerid_field ...

  5. あなたはインデックスを追加、しかし、join_buffer_sizeサーバー変数を増やすことを検討することをお勧めします最初の場所で多くを助ける必要があります。

+0

良い点が、私の場合はそれらのどれも助けられませんでした。 ORDER BYが問題を引き起こすことがわかりました。どのようにこれに取り組むための任意の提案?ありがとう – Genov

+0

それは力の指数が扱うことを意味したものです。どうやら、mysqlはソートのためにインデックスを使用することを容易には確信していません。おそらく、顧客テーブルからすべての行と列を返すためです。 – Shadow

+0

ええ、私の場合は助けになりません。試してくれてありがとう! – Genov

関連する問題