即使使用LIMITS,MySQL查询也会花费很长时间

时间:2019-07-08 19:15:04

标签: php mysql

1。总结问题

我们公司使用该系统已有很长时间了,人们感到系统运行缓慢。我无法重写代码,因为它是超级硬编码的,而且文件太多。

几个月前,我们看到一个查询执行大约需要170秒。 我的解决方法是为每个查询添加LIMITS,从170s下降到2-3s。但是上周我看到该代码现在大约需要5到25秒。

此系统也在php 5.2上。基本上无法升级代码以使其适用于5.6 3个人正在重写此代码,8小时后我们设法进入了登录页面。 索引是有限的,因为大多数数据库信息都使用字符串而不是整数。

2。提供背景,包括您已经尝试过的内容

我尝试过的事情:
-默认添加300个限制,用户也可以更改此限制。
-将服务器迁移到更好的硬件。
-提供更多的RAM(现在为10gb)和两个虚拟CPU。
-从本地存储迁移到网络(此时性能更好)。

3。显示一些代码

SELECT pastabos_apskaitininkui, 
       uzdaviniai.pakr_salis, 
       uzdaviniai.iskr_salis, 
       uzdaviniai.id                       AS uzdavinio_id, 
       salys.salis                         AS muitines_salis, 
       uzdaviniai.pakr_regionas, 
       uzdaviniai.iskr_regionas, 
       uzdaviniai.pakr_miestas, 
       uzdaviniai.iskr_miestas, 
       uzdavinio_priekaba, 
       priekabos.tipas                     AS priekabos_tipas, 
       uzdaviniai.kas_sukure_skyrius, 
       uzdaviniai.kam_sukure_skyrius, 
       uzdaviniai.kas_sukure_vadyb, 
       uzdaviniai.kam_sukure_vadyb, 
       uzdav_users.vardas_sutr             AS uzdav_user_vardas, 
       pakrov_salis.sutrumpinimas          AS uzdav_pakr_salis, 
       iskrov_salis.sutrumpinimas          AS uzdav_iskr_salis, 
       uzdaviniai.pasikrovimo_data         AS uzd_pasikrovimo_data, 
       uzdaviniai.pristatymo_data          AS uzd_pristatymo_data, 
       uzdaviniai.pastabos, 
       suma_vykdytojui_valiuta, 
       vykdytojui_valiuta, 
       uzdaviniai.eil_nr, 
       uzdaviniai.statusas, 
       uzdaviniai.statusas_baigtas_ranka, 
       keliones_lapas.reiso_nr, 
       keliones_lapas.masina, 
       keliones_lapas.masinos_id, 
       keliones_lapas.priekabos_nr, 
       keliones_lapas.priekabos_id, 
       keliones_lapas.priekabos2_nr, 
       keliones_lapas.reiso_pavadinimas, 
       keliones_lapas.vykdytojo_tipas, 
       keliones_lapas.vykdytojo_imone, 
       keliones_lapas.atvykimo_data, 
       keliones_lapas.vairuotojas, 
       keliones_lapas.vairuotojas2, 
       keliones_lapas.vairuotojas3, 
       keliones_lapas.vairuotojas4, 
       keliones_lapas.marsrutas, 
       klientai.firmos_pavadinimas         AS uzsakovas, 
       uzsakovo_uzs_nr, 
       valiutos.valiuta                    AS frachto_valiuta, 
       uzsakymas.vadybininkas, 
       uzsakymas.skyrius, 
       uzsakymas.frachtas_suma, 
       uzsakymas.pavadinimas, 
       uzsakymas.uzsakymo_id, 
       uzsakymas.reg_data, 
       uzsakymas.pastabos                  AS uzs_pastabos, 
       uzsakymas.statusas                  AS uzsakymo_statusas, 
       sask_ist.serija, 
       sask_ist.sask_nr, 
       sask_ist.id                         AS sask_id, 
       sask_ist.suma, 
       sask_ist.valiuta, 
       sask_ist.kursas                     AS sask_ist_kursas, 
       sask_ist.apmoketi_iki, 
       sask_ist.atidejimas, 
       issiuntimo_data, 
       sask_ist_apmokejimas.suma           AS ist_apm_suma, 
       sask_ist_apmokejimas.valiuta        AS ist_apm_valiuta, 
       sask_ist_apmokejimas.kursas         AS ist_apm_kursas, 
       sask_ist_apmokejimas.id             AS ist_apm_id, 
       klientu_pakr_vietos.pavadinimas     AS muitines_pavadinimas, 
       klientu_pakr_vietos.miestas         AS muitines_miestas, 
       klientu_pakr_vietos.adresas         AS muitines_adresas, 
       kokio_krovinio_dalis, 
       krovinys_konsoliduotas, 
       kroviniu_tipai.pavadinimas          AS krovinio_pavadinimas, 
       kroviniai.pasikrovimo_data, 
       kroviniai.pristatymo_data, 
       kroviniai.uzsakovo_krovinio_nr, 
       kroviniai.id                        AS krovinio_id, 
       svoris_t, 
       ldm, 
       turis, 
       paleciu_skaicius, 
       vnt, 
       temperature, 
       kroviniai.konteinerio_nr, 
       kroviniai.pakr_vietos_id            AS kr_pakr_vietos_id, 
       kroviniai.iskr_vietos_id            AS kr_iskr_vietos_id, 
       kroviniai.pakr_salis                AS kr_pakr_salis, 
       kroviniai.iskr_salis                AS kr_iskr_salis, 
       kroviniai.pakr_miestas              AS kr_pakr_miestas, 
       kroviniai.pakr_regionas             AS kr_pakr_regionas, 
       kroviniai.iskr_regionas             AS kr_iskr_regionas, 
       kroviniai.iskr_miestas              AS kr_iskr_miestas, 
       kroviniai.ismuitinimo_data          AS ismuitinimo_data, 
       kroviniai.uzmuitinimo_data          AS uzmuitinimo_data, 
       kroviniai.pasienio_postas           AS pasienio_postas, 
       kroviniai.ismuitinimo_vieta         AS ismuitinimo_vieta, 
       statusai.pavadinimas                AS st_pavadinimas, 
       st_uzsakymai.id                     AS st_id, 
       st_salys.salis                      AS st_salis, 
       st_uzsakymai.data                   AS st_data, 
       st_uzsakymai.laikas                 AS st_laikas, 
       st_uzsakymai.ivykio_pastabos_sutr   AS st_pastabos_sutr, 
       st_uzsakymai.ivykio_pastabos        AS st_pastabos, 
       st_keliones_lapas.reiso_pavadinimas AS st_reiso_pav, 
       vairuotojai.vardas                  AS sq_vardas, 
       priekabos.masinos_nr                AS sq_priekaba 
FROM   uzdaviniai 
       LEFT JOIN priekabos 
              ON priekabos.id = uzdaviniai.uzdavinio_priekaba 
       LEFT JOIN users AS uzdav_users 
              ON uzdav_users.id = uzdaviniai.kam_sukure_vadyb 
       LEFT JOIN salys AS pakrov_salis 
              ON pakrov_salis.id = uzdaviniai.pakr_salis 
       LEFT JOIN salys AS iskrov_salis 
              ON iskrov_salis.id = uzdaviniai.iskr_salis 
       LEFT JOIN uzsakymas 
              ON uzdaviniai.uzsakymo_id = uzsakymas.uzsakymo_id 
       LEFT JOIN uzd_kur_vykdytas 
              ON uzdaviniai.id = uzd_kur_vykdytas.uzdavinio_id 
       LEFT JOIN keliones_lapas 
              ON keliones_lapas.reiso_nr = uzd_kur_vykdytas.reiso_nr 
       LEFT JOIN st_uzsakymai 
              ON st_uzsakymai.uzdavinio_id = uzdaviniai.id 
       LEFT JOIN statusai 
              ON statusai.id = st_uzsakymai.statuso_id 
       LEFT JOIN salys AS st_salys 
              ON st_salys.id = st_uzsakymai.salis 
       LEFT JOIN keliones_lapas AS st_keliones_lapas 
              ON st_keliones_lapas.reiso_nr = st_uzsakymai.reiso_nr 
       LEFT JOIN vairuotojai 
              ON vairuotojai.id = keliones_lapas.vairuotojas 
       LEFT JOIN sask_ist_uz_ka 
              ON sask_ist_uz_ka.uzsakymo_id = uzsakymas.uzsakymo_id 
       LEFT JOIN sask_ist 
              ON sask_ist.id = sask_ist_uz_ka.sask_id 
       LEFT JOIN sask_ist_apmokejimas 
              ON sask_ist.id = sask_ist_apmokejimas.sask_id 
       LEFT JOIN uzsakymo_kroviniai 
              ON uzsakymas.uzsakymo_id = uzsakymo_kroviniai.uzsakymo_id 
       LEFT JOIN kroviniai 
              ON kroviniai.id = uzsakymo_kroviniai.krovinio_id 
       LEFT JOIN klientu_pakr_vietos 
              ON klientu_pakr_vietos.id = kroviniai.ismuitinimo_vieta 
       LEFT JOIN klientu_pakr_vietos AS iskr_vietos_uzd 
              ON iskr_vietos_uzd.id = uzdaviniai.pakr_vietos_id 
       LEFT JOIN salys 
              ON salys.id = klientu_pakr_vietos.salis 
       LEFT JOIN cmr_kroviniai 
              ON kroviniai.id = cmr_kroviniai.krovinio_id 
       LEFT JOIN cmr 
              ON cmr.id = cmr_kroviniai.cmr_id 
       LEFT JOIN cmr_panaudojimas 
              ON cmr_panaudojimas.cmr_id = cmr_kroviniai.cmr_id 
                 AND keliones_lapas.reiso_nr = cmr_panaudojimas.reiso_nr 
       LEFT JOIN kroviniu_tipai 
              ON kroviniu_tipai.id = kroviniai.krovinio_pavadinimas 
       LEFT JOIN klientai 
              ON klientai.id = uzsakymas.kliento_id 
       LEFT JOIN valiutos 
              ON valiutos.id = uzsakymas.frachtas_valiuta 
WHERE  1 = 1 
       AND ( `uzdaviniai`.`pasikrovimo_data` BETWEEN 
             '2019-07-08' AND '2019-07-08 23:59:59' 
           ) 
ORDER  BY uzdaviniai.pasikrovimo_data DESC 
LIMIT  300

如您所见,有很多左联接语句。

4。结果

我想要的是一些帮助,我可以用这垃圾做些什么,或者可以做些建议,我可以改变什么。我希望这些查询将花费越来越多的时间来执行。

2 个答案:

答案 0 :(得分:1)

如果直接在mysql控制台中执行查询时查询很快,那么查询根本没有问题,而慢速的是使用查询结果的php代码,未显示的php代码以及您应该在此处修改/发布。

如果即使在mysql控制台中查询速度仍然很慢,则问题可能出在主表/联接表的大小上(但这可以通过放宽mysql服务器的内存限制和/或将ram添加到服务器来解决) ,或者可能是对联接表的索引不正确,因为任何LEFT JOIN都需要在用于联接它的字段上对联接表进行索引(这可以通过在联接表上创建正确的索引来解决)。

答案 1 :(得分:0)

考虑更改您的

WHERE  1 = 1 
   AND ( `uzdaviniai`.`pasikrovimo_data` BETWEEN 
         '2019-07-08' AND '2019-07-08 23:59:59' 
       ) 

TO

uzdaviniai之间的pasikrovimo_data之间。              '2019-07-08'和'2019-07-08 23:59:59'

请告诉我们结果(带有反引号)。