1

我使用以下查询

SELECT a.job_number as f31jn, b.job_number as f32jn
FROM 
f31 a LEFT JOIN f32 b 
ON (a.job_number = b.job_number AND a.date_audit = b.date_audit)
WHERE date_format(a.date_audit, '%b %Y') = 'Dec 2012'
GROUP BY a.job_number, a.ref_id, b.job_number, b.ref_id

上述查询大约需要160秒才能完成。

我已向以下列添加索引:

f31 - job_number, date_audit (separate indexes)
f32 - job_number, date_audit (separate indexes)

EXPLAIN上述查询的结果 解释

编辑

将查询更改为

SELECT a.job_number as f31jn, b.job_number as f32jn
FROM 
f31 a LEFT JOIN f32 b 
ON (a.job_number = b.job_number AND a.date_audit = b.date_audit)
WHERE a.date_audit >= '2012-12-01' AND a.date_audit < '2013-01-01'
GROUP BY a.job_number, a.ref_id, b.job_number, b.ref_id

并且执行时间仍然没有下降。它保持在 150 到 160 秒的相同近似范围内。

现在EXPLAIN出现为 解释 2

对于 table a,它仍在搜索 90% 的记录(总记录在 68k 左右)。

4

2 回答 2

3

MySQL 不能使用索引来帮助处理date_format(a.date_audit, '%b %Y') = 'Dec 2012'.

您对 job_number 和 date_audit 是否有单独的索引或一个组合索引。如果它是一个组合索引,那么 MySQL 不能单独将它用于 date_audit 上的任何形式的查询。要么单独在 date_audit 上创建索引,要么首先创建 date_audit 和第二个 job_number 的组合索引。

然后将该WHERE子句转换为将 date_audit 与实际日期值进行比较。

这是在黑暗中拍摄的,但值得一试:

首先,计时:

SELECT * from f31 a 
WHERE a.date_audit >= '2012-12-01' 
  AND a.date_audit < '2013-01-01'

它应该很快。如果没有,您需要验证您的索引和列的类型(DATE、DATETIME 或 TIMESTAMP)date_audit

然后:

SELECT DISTINCT a.job_number as f31jn, b.job_number as f32jn
FROM 
  (SELECT * from f31 aa 
   WHERE aa.date_audit >= '2012-12-01' 
     AND aa.date_audit < '2013-01-01') as a    
LEFT JOIN f32 b 
ON (a.job_number = b.job_number AND a.date_audit = b.date_audit)

如果这不能解决问题,那么请使用架构和至少几条测试数据设置一个SQL Fiddle 。

于 2013-06-11T08:22:36.223 回答
1

考虑首先重构这部分:

date_format(a.date_audit, '%b %Y') = 'Dec 2012'

进入:

a.date_audit >= '2012-12-01' && a.date_audit < '2013-01-01'

还有一件事,尝试像这样添加组合索引:

f31 - (date_audit, job_number)
f32 - (date_audit, job_number)

MySQL 将只对每个表使用一个索引,因此将它们组合起来应该为连接和查询指定它们date_audit

于 2013-06-11T09:22:03.090 回答