非常慢的SQL查询,只有两个左连接

时间:2016-05-10 09:27:51

标签: mysql sql

我正在加入三张桌子' customer',' customer_address'和国家'使用左连接,因为我允许客户拥有一个或没有地址。 目前我有13k +客户,查询大约需要40秒。我尝试了内部联接,但在这种情况下,我没有让客户没有地址。 ' ON'中的所有列被编入索引,但它并没有太大的区别。 这是我的疑问:

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

2 个答案:

答案 0 :(得分:0)

你可以试试这个。您不需要使用第一个CASE语句,因为您永远不会将CustomerId作为NULL接收。我已经删除了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

答案 1 :(得分:0)

那么,您必须使用不使用任何索引的所有类型查询。其中一个甚至有可怕的文件存储,这是一个非常昂贵的操作。

  1. 在customer_address.customerid字段中添加索引。这将用于匹配customer_address表和主客户表中的记录。

  2. 列出要从查询中返回的列,不要使用*。例如,我不明白为什么你需要从客户和地址表中返回customerid。

  3. 摆脱第一个案例陈述。 customer.customerid字段将始终填充。

  4. 在customer表后添加索引提示,以使mysql考虑使用customerid索引进行排序:

    ... FROM customer FORCE INDEX index_name_forcustomerid_field ...

  5. 您可能需要考虑增加join_buffer_size服务器变量,但是,首先添加索引应该会有很大帮助。