[英]Slow query performance left joining a view
I have 2 tables: 我有2张桌子:
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
And a view (that returns the last 30 days from NOW()
): 还有一个视图(从
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())
Whenever I run a query, as for example: 每当我运行查询时,例如:
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`
it takes quite some time (~20 seconds). 这需要相当长的时间(约20秒)。
Here is an explain of the query: 这是查询的解释:
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
What can I do in order to improve my query? 我该怎么做才能改善查询? Why is it taking so long?
为什么要花这么长时间?
Most of the problems are here: 大多数问题在这里:
LEFT JOIN `CONSUMO` ON sub1.fecha = DATE_FORMAT(fechahora, "%M %e")
In particular: 尤其是:
Don't use LEFT
; 不要使用
LEFT
; you want all the rows, and no extra ones, correct? 您想要所有的行,而没有多余的行,对吗? So use a plain
JOIN
. 因此,请使用普通的
JOIN
。
Do index fechahora
. 做索引
fechahora
。
Don't use DESCRIBE
; 不要使用
DESCRIBE
; it is less descriptive than SHOW CREATE TABLE
. 它的描述性不如
SHOW CREATE TABLE
。
Rather than recomputing the last 30 days over and over; 而不是一遍又一遍地重新计算过去的30天; have a long table with several year's worth of dates, and use a
WHERE
clause to limit the desired rows. 有一个包含几年日期的长表,并使用
WHERE
子句限制所需的行。
Don't hide fechahora
inside a function. 不要将
fechahora
隐藏在函数中。 Rearrange the query so it looks like 重新排列查询,使其看起来像
ON fechahora >= ... sub1.fecha ... AND fechahora < ... sub1.fecha + INTERVAL 1 DAY ... 在fechahora> = ... sub1.fecha ...和fechahora <... sub1.fecha +间隔1天...
The ...
needs to be whatever it takes to do the inverse of "%M %e". ...
必须是执行“%M%e”逆运算所需的一切。 You would probably be better off changing last_30_days
to compute a plain DATE
datatype. 您最好更改
last_30_days
以计算普通的DATE
数据类型。 If/when you need a particular formatting in the output, do it in the SELECT
. 如果/当您需要输出中的特定格式时,请在
SELECT
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.