简体   繁体   English

查询性能下降,导致无法加入视图

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM