长MYSQL查询执行

长MYSQL查询执行,mysql,database,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

我有一个查询问题,需要监控状态仓库、输入、输出、债务、卸载

查询:

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)
  • 输出=>izlaz(kolicinaIzlaza)
  • 返回仓库=>povracaj(kolicinaPovracaj)
  • 拆除的OTPI(kolicinaOtpis)
  • 与工人一起退役=>razd(KolicinaRazd)

谢谢

如评论部分所述,您可以将select子句缩减为
ulaz.mac不为空
。原因是您希望保证至少有一个不为null。因此,当ulaz.mac不为null时,标准为fullfilled。当ulaz.mac为null时,则不满足加入条件,因此所有mac都将为null

如果dbms没有检测到这种情况,这可以加快查询速度。随着前面提到的标准的减少,很明显必须读取ulaz的哪一部分(如果你甚至在它上面有一个索引,这可能会非常快)。当然,dbms仍然必须连接所有其他表。macs上的索引也会有所帮助

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上有索引,那么EXISTS应该非常快。然后你需要从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子句更接近我们要查找的内容,我们保存了许多联接及其大的中间结果。好的,试一试。

我们可以看看您的问题吗?请查看查询计划。足够的英语提问(以“?”结尾)。哦,首先,对它进行重新格式化,以消除所有的差异,这些通常是“伙计,你把一切都拖慢了”的部分,并指出一个糟糕的查询开始。你知道,这有助于将查询中的所有单词翻译成英语。你的数据库是什么?Mysql和sql server是两个不同的野兽。ulaz的主键是什么?西夫拉?雨衣?还有别的吗?我是新来的,有点难以相处!对不起我的英语:(问题是查询执行时间的长度已经结束(查询耗时407.2486秒)我请求作为一个操作请求并给出准确的结果,所有必须调整并稍微加快。旧查询:显示第0-14行(总共15行,查询耗时458.7143秒)现在显示第0-14行(总共15次,查询耗时254.9191秒)做得好,谢谢