长MYSQL查询执行

时间:2014-09-16 10:12:25

标签: mysql database

我的查询问题需要监控州仓库,输入,输出,债务,卸货......

查询:

SELECT CONCAT(ulaz.sifra, ' - ', ulaz.uredjaj) AS uredjaj,
       COUNT(DISTINCT ulaz.mac) AS kolicinaUlaza,
       COUNT(DISTINCT izlaz.mac) AS kolicinaIzlaza,
       COUNT(DISTINCT povracaj.mac) AS kolicinaPovracaj,
       COUNT(DISTINCT otpis.mac) AS kolicinaOtpis,
       COUNT(DISTINCT razd.mac1) AS kolicinaRazd,
       sifr.min_kolicina AS minimalnaKolicina 
FROM ulaz_u AS ulaz 
       LEFT JOIN zaduzenje_u AS izlaz ON ulaz.mac = izlaz.mac 
       LEFT JOIN povracaj_u AS povracaj ON ulaz.mac = povracaj.mac 
       LEFT JOIN otpis AS otpis ON ulaz.mac = otpis.mac 
       LEFT JOIN razduzenje_u AS razd on ulaz.mac = razd.mac1 
       LEFT JOIN sifrarnik as sifr on ulaz.sifra = sifr.sifra 
WHERE ulaz.mac is not NULL 
      OR izlaz.mac is not null   
      OR povracaj.mac is not null 
      OR otpis.mac is not null 
      OR razd.mac1 is not null 
GROUP BY ulaz.sifra

数据库是Mysql

我的问题是如何加快查询的执行速度?

仓库:

  • 序列号 => sifra
  • 设备名称 => uredjaj
  • 输入 => ulaz(kolicinaUlaza)
  • 输出 =>伊兹拉兹(kolicinaIzlaza)
  • 返回仓库 => povracaj(kolicinaPovracaj)
  • 已拆除 => otpis(kolicinaOtpis)
  • 退役工人 =>拉兹德(KolicinaRazd)

谢谢

1 个答案:

答案 0 :(得分:0)

如评论部分所述,您可以将select子句缩减为ulaz.mac IS NOT NULL。原因是你希望保证至少有一个不是null。因此,当ulaz.mac不为null时,标准已满。当ulaz.mac为null时,则不符合您的连接条件,因此所有mac都将为null。

如果dbms没有检测到这种情况,这可以加快查询速度。如上所述减少标准,很明显必须读取ulaz的哪一部分(如果你甚至有一个索引,这可能会非常快)。当然,dbms仍然必须加入所有其他表。 Mac上的索引再次有用。

SELECT CONCAT(ulaz.sifra, ' - ', ulaz.uredjaj) AS uredjaj,
       COUNT(DISTINCT ulaz.mac) AS kolicinaUlaza,
       COUNT(DISTINCT izlaz.mac) AS kolicinaIzlaza,
       COUNT(DISTINCT povracaj.mac) AS kolicinaPovracaj,
       COUNT(DISTINCT otpis.mac) AS kolicinaOtpis,
       COUNT(DISTINCT razd.mac1) AS kolicinaRazd,
       sifr.min_kolicina AS minimalnaKolicina
FROM ulaz_u AS ulaz
LEFT JOIN zaduzenje_u AS izlaz ON ulaz.mac = izlaz.mac
LEFT JOIN povracaj_u AS povracaj ON ulaz.mac = povracaj.mac
LEFT JOIN otpis AS otpis ON ulaz.mac = otpis.mac
LEFT JOIN razduzenje_u AS razd ON ulaz.mac = razd.mac1
LEFT JOIN sifrarnik AS sifr ON ulaz.sifra = sifr.sifra
WHERE ulaz.mac IS NOT NULL
GROUP BY ulaz.sifra;

另一种方法是预先聚合。首先选择所有mac以查看它们存在于哪些表中。你不经常感兴趣,但只是对是或否。你用EXISTS来测试它,如果mac上有索引,它应该非常快。那么你需要来自ulaz的独特的sifra + mac。加入这些并总结存在计数器。

SELECT 
  CONCAT(ulaz.sifra, ' - ', ulaz.uredjaj) AS uredjaj,
  COUNT(*) AS kolicinaUlaza,
  SUM(macs.is_islaz) AS kolicinaIzlaza,
  SUM(macs.is_povracaj) AS kolicinaPovracaj,
  SUM(macs.is_otpis) AS kolicinaOtpis,
  SUM(macs.is_razd) AS kolicinaRazd,
  sifr.min_kolicina AS minimalnaKolicina
FROM 
(
  SELECT sifra, mac, uredjaj 
  FROM ulaz_u 
  WHERE mac IS NOT NULL
  GROUP by sifra, mac
) AS ulaz
INNER JOIN
(
  SELECT
    ulaz_macs.mac,
    CASE WHEN EXISTS (select * FROM zaduzenje_u AS izlaz WHERE ulaz_macs.mac = izlaz.mac) THEN 1 ELSE 0 END AS has_islaz,
    CASE WHEN EXISTS (select * FROM povracaj_u AS povracaj WHERE ulaz_macs.mac = povracaj.mac) THEN 1 ELSE 0 END AS has_povracaj,
    CASE WHEN EXISTS (select * FROM otpis AS otpis WHERE ulaz_macs.mac = otpis.mac) THEN 1 ELSE 0 END AS has_otpis,
    CASE WHEN EXISTS (select * FROM razduzenje_u AS razd WHERE ulaz_macs.mac = razd.mac) THEN 1 ELSE 0 END AS has_razd
  FROM (SELECT DISTINCT mac FROM ulaz_u) AS ulaz_macs
) AS macs ON macs.mac = ulaz.mac
LEFT JOIN sifrarnik AS sifr ON ulaz.sifra = sifr.sifra
GROUP BY ulaz.sifra;

这可能更快或更快。 MySQL以连接速度最快而闻名。但是,exists子句更接近我们正在寻找的东西,并且我们保存了许多连接及其大的中间结果。好吧,试试吧。