加速mysql查询

时间:2015-07-31 08:42:43

标签: php mysql join query-optimization

我在MySQL中有这个查询。此查询运行时间太长,我知道问题是选择器(coalesce ((SELECT ...),我不知道如何通过加入来加速查询。

我希望你们中的一些SQL大师能够帮助我。

SELECT
    COALESCE(
        (SELECT CONCAT(d.PRIJEVOZNIK, ' ', d.VOZAC_TRANSFER) 
         FROM dokum_zag as d
         where d.SIFKNJ='NP' and
               d.ID_VEZA=dokum_zag.ID and 
               d.korisnicko_ime=dokum_zag.korisnicko_ime 
         ),'') as PRIJEVOZNIK,
      (RELACIJA_TRANS_VOZ_TRANS) as RELACIJA_TRANS_VOZ, 
      (PRIJEVOZNIK_POVRATNI_TRANS) as PRIJEVOZNIK_POVRATNI, 
      (VAUC_KNJIZENO_TRANS) as VAUC_KNJIZENO, 
      ID_NALOGA, 
      ID_NALOGA_POV, 
      ID_VAUCHER, 
      DOLAZAK, VRIJ_TRANSFER,ODLAZAK,VRIJEME_LETA_POVRAT ,BRDOK, NOSITELJ_REZ, RELACIJA_TRANS, VOZILO_NAZIV, BROJ_NALOGA,BROJ_NAL_POV,BROJ_VAUCHER,BROJ_SOBE,VALIZN,PAX, MPIZN,ID 
FROM
    dokum_zag 
WHERE 
    korisnicko_ime = '10' and 
    ((DOLAZAK='2015-07-30') or (ODLAZAK='2015-07-30')) and 
    STORNO <> 'DA' and 
    SIFKNJ = 'TR' and 
   ((YEAR(DOLAZAK)= '2015') or (YEAR(ODLAZAK)= '2015')) 
order by 
   (CASE WHEN DOLAZAK < '2015-07-30' THEN ODLAZAK ELSE DOLAZAK END) , 
   (CASE WHEN DOLAZAK < '2015-07-30' THEN VRIJEME_LETA_POVRAT ELSE VRIJ_TRANSFER END), ID 

2 个答案:

答案 0 :(得分:0)

如果没有数据库结构,并且您想要提取的内容的说明有点难以帮助您。

从逻辑的角度来看,某些事情是多余的,例如

((DOLAZAK='2015-07-30') or (ODLAZAK='2015-07-30')) and 
...
((YEAR(DOLAZAK)= '2015') or (YEAR(ODLAZAK)= '2015')) 

年份部分没有必要,因为前两年指定了年份。

可能让服务器疯狂的另一件事是奇怪的order by子句,因为它从一个记录变为另一个记录(测试它固定在一个字段上的设置)。

您还可以检查是否为外部where子句中的所有字段正确设置了索引,而非数字字段的索引不是varchars(例如SIFKNJ和{{1}应该是STORNO)。

char(2)部分可以通过coalesce解决,因此不会计算每一行。但这取决于你想从数据库中提取的内容和方式......(因为那个子查询在outer join部分有自己的字段......很奇怪)

希望这能有所帮助

答案 1 :(得分:0)

INDEX(korisnicko_ime, SIFKNJ)

(in either order) may help

Turning the correlated subquery into a JOIN may help.

((DOLAZAK='2015-07-30') or (ODLAZAK='2015-07-30')) and 
((YEAR(DOLAZAK)= '2015') or (YEAR(ODLAZAK)= '2015')) 

is a bit weird. This might help:

( SELECT ... 
     AND DOLAZAK ='2015-07-30' AND ODLAZAK >= '2015-01-01'
                               AND ODLAZAK  < '2015-01-01' + INTERVAL 1 YEAR
) UNION DISTINCT
( SELECT ... 
     AND ODLAZAK ='2015-07-30' AND DOLAZAK >= '2015-01-01'
                               AND DOLAZAK  < '2015-01-01' + INTERVAL 1 YEAR
) ORDER BY ...

To help that reformulation, add 2 composite indexes:

INDEX(korisnicko_ime, SIFKNJ, DOLAZAK, ODLAZAK)
INDEX(korisnicko_ime, SIFKNJ, ODLAZAK, DOLAZAK)