Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Explique o plano de desempenho do mysql usando o uso temporário; Usando classificação de arquivos; Usando condição de índice


Forneça SHOW CREATE TABLE .

O filtro principal parece ser
            where  dsr_booking_date BETWEEN '2017-05-01' AND '2017-06-30'
              AND  LENGTH(dsr_cnno)=9
              AND  DSR_BOOKED_BY ='F'
              AND  dsr_status<>'R'
              AND  dsr_cnno NOT LIKE 'J%'
              AND  dsr_cnno NOT LIKE '@%'
              AND  dsr_cnno NOT LIKE '576%'
              AND  dsr_cnno NOT LIKE 'I3%'
              AND  dsr_cnno NOT LIKE '7%'
              AND  dsr_cnno NOT LIKE 'N%'
              and  d.dsr_dest_pin>0

Provavelmente o único índice útil para isso é, nesta ordem:
INDEX(DSR_BOOKED_BY, dsr_booking_date)

Coisas como
ifnull((select max(ndsr_ins_amt)     from ndx_dsr_table where ndsr_cnno=dsr_cnno ),0)-
ifnull((select max(ndsr_serv_charge) from ndx_dsr_table where ndsr_cnno=dsr_cnno ),0) -

provavelmente deve ser feito em conjunto. Considere algo como
ifnull(mm.max_nia), 0) -
ifnull(mm.max_nsc), 0) .
...
LEFT JOIN ( SELECT max(ndsr_ins_amt)     AS max_nia,
                   max(ndsr_serv_charge) AS max_nsc
                from ndx_dsr_table
          ) AS mm  ON ndsr_cnno=dsr_cnno

Ou, se necessário, crie uma tabela temporária com essa subconsulta e, em seguida, LEFT JOIN para ela.

(Como você não qualificou cada coluna com a tabela em que está, não posso ser mais específico.)

Você tem índices 'compostos' adequados para os vários JOINs ?

De acordo com o EXPLAIN , ele está verificando 182 milhões de linhas de dsr_table . Portanto, meu índice acima provavelmente ajudará (se você ainda não tiver um semelhante.)

Hesito em sugerir um índice tão longo, mas isso pode ajudar:
INDEX(DSR_BOOKED_BY, dsr_booking_date,  -- these first, in this order
      dsr_cnno, dsr_status, dsr_cnno, dsr_dist_pin,  -- in any order
      id)   -- (whatever the PK of the table is); last

Problema ruim na segunda consulta
        WHERE  dsr_booking_date = '2017-04-30'
          AND  '2017-05-30'

Talvez você quis dizer 31 dias:
        WHERE  dsr_booking_date BETWEEN '2017-04-30'
                                   AND  '2017-05-30'

Ou talvez 2 dias:
        WHERE  dsr_booking_date IN ('2017-04-30', '2017-05-30')

O que você tem é
        WHERE  dsr_booking_date = '2017-04-30'  -- test for one day
          AND  true  -- that's how '2017-05-30' is interpreted