2014-02-21 62 views
0

我有一个查询MySQL查询优化与内部联接

$query = "SELECT DISTINCT report_date,weekreportDate FROM contract_sales a 
    INNER JOIN contract b ON a.contract_UUID = b.UUID 
    INNER JOIN geoPoint c ON b.customer_UUID = c.customerUUID 
    WHERE c.com_UUID = '$com' AND a.report_date >= Date('$dateafter') 
    AND c.city_UUID = '$cit' ORDER BY `report_date`"; 

,我需要做的是先干掉通过日期过滤所有的结果,但你可以看到我得到的一切,然后做我的日期排序在检查..

我内心加入所有这些 - 有没有更好的方式来做到这一点?

我对每个日期都有一个报告 - 并且有两年的数据 - 我想在2014年只有日期,所以你可以看到我有700多个日期对我来说很无用,但我必须经过他们都可以检查其他字符串UUID以及...我能做些什么来加速我的(工作 - 虽然执行缓慢)?

解释信息的要求:

Generation Time: Feb 20, 2014 at 06:48 PM 
Generated by: phpMyAdmin 3.3.10.4/MySQL 5.1.53-log 
SQL query: EXPLAIN SELECT DISTINCT report_date,weekreportDate FROM contract_sales a INNER JOIN contract b ON a.contract_UUID = '1234' INNER JOIN geoPoint c ON b.customer_UUID = '1234' WHERE c.com_UUID = '1234' AND a.report_date >= Date('2014-01-01') AND c.city_UUID = '1234' ORDER BY `report_date`; 
Rows: 3 

id select_type table type possible_keys key key_len ref rows Extra 
1 SIMPLE a ref uuid_conlcs uuid_conlcs 110 const 1 Using where; Using temporary; Using filesort 
1 SIMPLE b ref uuid_cust uuid_cust 110 const 1 Using where; Using index; Distinct 
1 SIMPLE c ref uuid_gargp,uuid_citgp uuid_citgp 110 const 1 Using where; Distinct 

回答

1

首先,你的查询重写。我不会建议使用别名只是a,b,c,但是更接近于contract_sales的表“cs”的上下文,合同的“con”以及geoPoint的“gp”......在较大的更复杂的查询中更加容易。

此外,总是尝试使用table.column(或alias.column)限定您的查询,因为WeekReportDate不清楚,但它似乎与您的合同销售表相关联。

至于这个构造的索引,我会有一个索引(report_date,weekreportDate,contract_uuid)。通过这种方式,它可以处理被检索的列,where子句,order by和合同表的连接,而无需返回到原始数据页面。

合约表,我会有一个关于(UUID,customer_UUID)的索引,也是合约销售连接的覆盖索引,也支持到geoPoint表的连接。

最后,您的geoPoint表格(customerUUID,com_uuid,city_uuid)上的索引也覆盖了联接和您的过滤标准。

SELECT DISTINCT 
     cs.report_date, 
     cs.weekreportDate 
    FROM 
     contract_sales cs 
     INNER JOIN contract con 
      ON cs.contract_UUID = con.UUID 
      INNER JOIN geoPoint gp 
       ON con.customer_UUID = gp.customerUUID 
       AND gp.com_UUID = '$com' 
       AND gp.city_UUID = '$cit' 
    WHERE 
     cs.report_date >= Date('$dateafter') 
    ORDER BY 
     cs.report_date 

现在这样说,我不知道你的表音量的妆,但如果你正在寻找的东西特定COM /城市,我会怀疑记录排位赛,这将是一个问题日期范围内比所有COM /城市要小得多。所以,我会按照以下方式反转查询,希望较小的数据集可能会更快地查询,但是您必须明确地尝试两种方法。

SELECT DISTINCT 
     cs.report_date, 
     cs.weekreportDate 
    FROM 
     geoPoint gp 
     INNER JOIN contract con 
      ON gp.customerUUID = con.customer_UUID 
      JOIN contract_sales cs 
       ON con.UUID = cs.contract_UUID 
       AND cs.report_date >= Date('$dateafter') 
    WHERE 
      gp.com_UUID = '$com' 
     AND gp.city_UUID = '$cit' 
    ORDER BY 
     cs.report_date 

其实GeoPoint的指数应该在你的WHERE条件,然后再对客户UUID的加入到下一个表(com_uuid,city_uuid,customeruuid)。 (contract_UUID,report_date)上的contract_sales索引以及(customer_UUID,UUID)上的合同表索引,以匹配此查询的连接流。

+0

谢谢您的详细信息!它需要我花一些时间来消化你所说的内容,但是从最初的阅读中我认为我理解并且会给出这个答案!欣赏它! – morty346

+0

@ morty346,抱歉后期编辑,但第二次查询实际上会有不同的索引,因为我修改了答案上下文。 – DRapp