2016-05-10 38 views
0

我正在使用左連接加入三個表'customer','customer_address'和'country',因爲我允許客戶擁有一個地址或沒有地址。 目前我有13k +客戶,查詢大約需要40秒。我嘗試了內部連接,但在這種情況下,我沒有找到沒有地址的客戶。 'ON'中的所有列都被編入索引,但它沒有太大區別。 這裏是我的查詢:只有兩個左連接的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 

任何幫助,將不勝感激

編輯:

這裏是 '解釋' 的三個表:

客戶

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'

編輯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 

編輯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's ...既不是性能如何? – xarmengol

回答

0

你可以試試這個。您不需要使用第一個CASE語句,因爲您永遠不會將CustomerId接收爲NULL。我已刪除了ORDER BY子句太​​爲我假定這將提高查詢性能比較(客戶ID是主鍵,它顯示的記錄是如何組織安排在數據庫中,默認排列順序是升序)

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

嗯,你必須對所有不使用任何索引的類型查詢。其中之一甚至有可怕的filesort,這是一個非常昂貴的操作。

  1. 在customer_address.customerid字段中添加一個索引。這將用於將customer_address表中的記錄與主客戶表中的記錄進行匹配。

  2. 列出要從查詢中返回的列,請勿使用*。例如,我不明白爲什麼您需要從客戶和地址表中返回customerid。

  3. 擺脫第一例病例陳述。 customer.customerid字段將始終填充。

  4. customer表後添加一個索引提示,以使MySQL考慮使用在客戶指標進行排序:

    ... FROM customer FORCE INDEX index_name_forcustomerid_field ...

  5. 你可能要考慮但增加join_buffer_size服務器變量,添加索引首先應該幫助很多。

+0

好點,但沒有一個在我的情況幫助。我發現ORDER BY導致了這個問題。任何建議如何解決這個問題?謝謝 – Genov

+0

這就是力量指數要解決的問題。顯然,mysql不太容易使用索引進行排序。可能是因爲您要返回客戶表中的所有行和列。 – Shadow

+0

是的,但它對我的情況沒有幫助。感謝您的嘗試! – Genov