sql >> Base de Datos >  >> RDS >> Mysql

Explique el plan en el rendimiento de mysql usando Uso temporal; Usando ordenación de archivos; Usando la condición de índice

Proporcione SHOW CREATE TABLE .

El 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

Probablemente el único índice útil para eso es, en este orden:

INDEX(DSR_BOOKED_BY, dsr_booking_date)

Cosas 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) -

probablemente debería hacerse juntos. 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

O, si es necesario, cree una tabla temporal con esa subconsulta, luego LEFT JOIN a ella.

(Dado que no calificó cada columna con la tabla en la que se encuentra, no puedo ser más específico).

¿Tiene índices 'compuestos' adecuados para los distintos JOINs? ?

De acuerdo con EXPLAIN , está escaneando 182 millones de filas de dsr_table . Por lo tanto, es probable que mi índice, arriba, ayude (si aún no tiene uno similar).

Dudo en sugerir un índice tan largo, pero esto podría ayudar:

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 incorrecto en la segunda consulta

        WHERE  dsr_booking_date = '2017-04-30'
          AND  '2017-05-30'

Quizás quisiste decir 31 días:

        WHERE  dsr_booking_date BETWEEN '2017-04-30'
                                   AND  '2017-05-30'

O tal vez 2 días:

        WHERE  dsr_booking_date IN ('2017-04-30', '2017-05-30')

Lo que tienes es

        WHERE  dsr_booking_date = '2017-04-30'  -- test for one day
          AND  true  -- that's how '2017-05-30' is interpreted