内部联接的mysql查询优化

时间:2014-02-21 02:15:48

标签: php mysql sql performance

我有一个查询

$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 个答案:

答案 0 :(得分:1)

首先,重写您的查询。我建议不要使用别名a,b,c,而是更接近于合约表的“cs”上下文,合同的“con”和geoPoint的“gp”......在更大的更复杂的查询中尤其容易。 / p>

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

对于这个构造中的索引,我会有一个索引(report_date,weekreportDate,contract_uuid)。这样,它就是一个覆盖索引,用于处理要检索的列,where子句,order by和join表,无需返回到原始数据页。

合约表,我有一个(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 / City的东西,我会怀疑那些合格的记录会比有关日期范围的所有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_UID,report_date)上的contract_sales索引和(customer_UUID,UUID)上的合同表索引,以匹配此查询的连接流。