[英]Mysql query taking long time even with LIMITS
1. 总结问题
我们公司已经使用这个系统很长时间了,人们感觉系统速度非常慢。 我无法重写代码,因为它的超级硬编码和太多文件无法重写。
几个月前,我们看到一个查询的执行时间大约为 170 秒。 我的解决方法是为每个查询添加 LIMITS,从 170 秒减少到 2-3 秒。 但上周我看到该代码现在需要大约 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
如您所见,有许多 left join 语句。
4. 结果
我想要的是一些帮助我可以用这块废话做什么或一些建议我可以改变什么。 正如我预计这些查询将花费越来越多的时间来执行。
如果直接在mysql控制台执行查询速度快,那么查询完全没有问题,慢的是使用查询结果的php代码,你没有显示的php代码,你应该修改/在这里发帖。
如果即使在 mysql 控制台中查询也很慢,那么问题可能是主表/联接表的大小(但这可以通过放宽 mysql 服务器的内存限制和/或向服务器添加内存来解决),或者可能对连接表进行不正确的索引,因为任何 LEFT JOIN 都需要在用于连接它的字段上对连接表进行索引(这可以通过在连接表上创建正确的索引来解决)。
考虑改变你的
WHERE 1 = 1
AND ( `uzdaviniai`.`pasikrovimo_data` BETWEEN
'2019-07-08' AND '2019-07-08 23:59:59'
)
到
哪里uzdaviniai
。 pasikrovimo_data
BETWEEN '2019-07-08' 和 '2019-07-08 23:59:59'
请让我们知道结果(带反引号)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.