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