我有两张桌子:
describe CONSUMO
Field Type Null Key Default Extra
idconsumo int(11) NO PRI NULL auto_increment
idkey int(11) NO MUL NULL
ip varchar(50) NO Unknown
fechahora datetime NO NULL
describe CONTRATADO
Field Type Null Key Default Extra
idkey int(11) NO PRI NULL auto_increment
idusuario int(11) NO MUL NULL
idproducto int(11) NO MUL NULL
key varchar(64) NO MUL NULL
descripcion varchar(50) YES "API KEY"
peticiones int(11) YES NULL
caducidad datetime YES NULL
一个视图(返回NOW()
的最后30天):
CREATE VIEW `last_30_days` AS
SELECT
DATE_FORMAT((NOW() - INTERVAL ((`units`.`i` + (`tens`.`i` * 10)) + (`hundreds`.`i` * 100)) DAY),
'%M %e') AS `fecha`,
DATE_FORMAT((NOW() - INTERVAL ((`units`.`i` + (`tens`.`i` * 10)) + (`hundreds`.`i` * 100)) DAY),
'%Y%m%d') AS `fecha_order`
FROM
((`0_9_range` `units`
JOIN `0_9_range` `tens`)
JOIN `0_9_range` `hundreds`)
WHERE
((NOW() - INTERVAL ((`units`.`i` + (`tens`.`i` * 10)) + (`hundreds`.`i` * 100)) DAY) BETWEEN (NOW() - INTERVAL 1 MONTH) AND NOW())
每当我运行查询时,例如:
SELECT sub1.fecha, COUNT(idconsumo) as consumo
FROM `last_30_days` `sub1`
LEFT JOIN `CONSUMO` ON sub1.fecha = DATE_FORMAT(fechahora, "%M %e")
LEFT JOIN `CONTRATADO` ON CONSUMO.idkey = CONTRATADO.idkey
WHERE idusuario IS NULL OR idusuario = 1
GROUP BY `sub1`.`fecha`
ORDER BY `sub1`.`fecha_order`
需要相当长的时间(约20秒)。
以下是对查询的解释:
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived3> ALL NULL NULL NULL NULL 10 "Using temporary; Using filesort"
1 PRIMARY <derived13> ALL NULL NULL NULL NULL 10 "Using join buffer"
1 PRIMARY <derived23> ALL NULL NULL NULL NULL 10 "Using where; Using join buffer"
1 PRIMARY CONSUMO ALL NULL NULL NULL NULL 908553
1 PRIMARY CONTRATADO eq_ref PRIMARY PRIMARY 4 c1geoapi.CONSUMO.idkey 1 "Using where"
23 DERIVED NULL NULL NULL NULL NULL NULL NULL "No tables used"
24 UNION NULL NULL NULL NULL NULL NULL NULL "No tables used"
25 UNION NULL NULL NULL NULL NULL NULL NULL "No tables used"
26 UNION NULL NULL NULL NULL NULL NULL NULL "No tables used"
27 UNION NULL NULL NULL NULL NULL NULL NULL "No tables used"
28 UNION NULL NULL NULL NULL NULL NULL NULL "No tables used"
29 UNION NULL NULL NULL NULL NULL NULL NULL "No tables used"
30 UNION NULL NULL NULL NULL NULL NULL NULL "No tables used"
31 UNION NULL NULL NULL NULL NULL NULL NULL "No tables used"
32 UNION NULL NULL NULL NULL NULL NULL NULL "No tables used"
NULL "UNION RESULT" <union23,24,25,26,27,28,29,30,31,32> ALL NULL NULL NULL NULL NULL
13 DERIVED NULL NULL NULL NULL NULL NULL NULL "No tables used"
14 UNION NULL NULL NULL NULL NULL NULL NULL "No tables used"
15 UNION NULL NULL NULL NULL NULL NULL NULL "No tables used"
16 UNION NULL NULL NULL NULL NULL NULL NULL "No tables used"
17 UNION NULL NULL NULL NULL NULL NULL NULL "No tables used"
18 UNION NULL NULL NULL NULL NULL NULL NULL "No tables used"
19 UNION NULL NULL NULL NULL NULL NULL NULL "No tables used"
20 UNION NULL NULL NULL NULL NULL NULL NULL "No tables used"
21 UNION NULL NULL NULL NULL NULL NULL NULL "No tables used"
22 UNION NULL NULL NULL NULL NULL NULL NULL "No tables used"
NULL "UNION RESULT" <union13,14,15,16,17,18,19,20,21,22> ALL NULL NULL NULL NULL NULL
3 DERIVED NULL NULL NULL NULL NULL NULL NULL "No tables used"
4 UNION NULL NULL NULL NULL NULL NULL NULL "No tables used"
5 UNION NULL NULL NULL NULL NULL NULL NULL "No tables used"
6 UNION NULL NULL NULL NULL NULL NULL NULL "No tables used"
7 UNION NULL NULL NULL NULL NULL NULL NULL "No tables used"
8 UNION NULL NULL NULL NULL NULL NULL NULL "No tables used"
9 UNION NULL NULL NULL NULL NULL NULL NULL "No tables used"
10 UNION NULL NULL NULL NULL NULL NULL NULL "No tables used"
11 UNION NULL NULL NULL NULL NULL NULL NULL "No tables used"
12 UNION NULL NULL NULL NULL NULL NULL NULL "No tables used"
NULL "UNION RESULT" <union3,4,5,6,7,8,9,10,11,12> ALL NULL NULL NULL NULL NULL
为了改善查询,我该怎么办?为什么需要这么长时间?
答案 0 :(得分:1)
大多数问题都在这里:
LEFT JOIN `CONSUMO` ON sub1.fecha = DATE_FORMAT(fechahora, "%M %e")
特别是:
不要使用LEFT
;你想要所有的行,没有额外的行,对吗?因此,请使用普通JOIN
。
执行索引fechahora
。
不要使用DESCRIBE
;它的描述性低于SHOW CREATE TABLE
。
而不是一遍又一遍地重新计算过去30天;有一个包含几年日期值的长表,并使用WHERE
子句来限制所需的行。
不要在函数中隐藏fechahora
。重新排列查询,使其看起来像
ON fechahora&gt; = ... sub1.fecha ... 和fechahora&lt; ... sub1.fecha + INTERVAL 1 DAY ...
...
需要做出与“%M%e”相反的任何操作。您可能最好更改last_30_days
以计算普通DATE
数据类型。如果/当您需要输出中的特定格式时,请在SELECT
。