我遇到了Select性能问题,如何才能提高SQL的效率?
SELECT
O.DT_OCORRENCIA,
S.NU_SMP,
CLI.NM_APELIDO CLI,
TRANS.NM_ENTIDADE TRANS,
TPO.DS_TIPO_OCORRENCIA,
O.DS_OCORRENCIA,
REPLACE(FNC_RETORNA_MOTORISTAS(S.CD_SMP), '<br>', ';') AS NOME_MOTORISTA,
OG.DS_NOME AS DS_NOME_ORIGEM,
DG.DS_NOME AS DS_NOME_DESTINO,
U.NM_LOGIN AS DS_USUARIO_OCORRENCIA,
CASE
WHEN O.CD_USUARIO_INFORMOU = 717 THEN
'NAO'
ELSE
'SIM'
END FL_MANUAL,
CASE
WHEN (O.FL_ENVIOU_EMAIL_CLIENTE = 'S' OR O.FL_ENVIOU_EMAIL_TRANSP = 'S') THEN
'SIM'
ELSE
'NÃO'
END ENVIOU_EMAIL,
DECODE(O.NU_LOCAL_OCORRENCIA,
'1',
'Origem',
'2',
'Em transito',
'3',
'Alvos',
'4',
'Indiferente') DS_LOCAL_OCORRENCIA,
TOPER.DS_TIPO_OPERACAO
FROM TB_SMP S
INNER JOIN TB_OCORRENCIA O
ON O.CD_SMP = S.CD_SMP
INNER JOIN TB_TIPO_OCORRENCIA TPO
ON O.CD_TIPO_OCORRENCIA = TPO.CD_TIPO_OCORRENCIA
LEFT JOIN TB_TIPO_OPERACAO TOPER
ON TOPER.CD_TIPO_OPERACAO = S.CD_TIPO_OPERACAO
LEFT JOIN TB_USUARIO U
ON U.CD_USUARIO = O.CD_USUARIO_INFORMOU
LEFT JOIN TB_ENTIDADE CLI
ON CLI.CD_ENTIDADE = S.CD_ENTIDADE_CLIENTE
LEFT JOIN TB_ENTIDADE TRANS
ON TRANS.CD_ENTIDADE = S.CD_ENTIDADE_TRANSPORTADOR
LEFT JOIN TB_PONTO_GEOREFERENCIADO OG
ON OG.CD_PONTO_GEOREFERENCIADO = S.CD_PONTO_GEO_ORIGEM
LEFT JOIN TB_PONTO_GEOREFERENCIADO DG
ON (S.CD_PONTO_GEO_DESTINO IS NULL AND
DG.CD_PONTO_GEOREFERENCIADO =
FNC_GET_ULTIMA_ENTREGA_PONTO(S.CD_SMP))
OR (S.CD_PONTO_GEO_DESTINO IS NOT NULL AND
DG.CD_PONTO_GEOREFERENCIADO = S.CD_PONTO_GEO_DESTINO)
WHERE EXISTS (SELECT 1
FROM TB_TIPO_OCORRENCIA T
WHERE T.CD_TIPO_OCORRENCIA = O.CD_TIPO_OCORRENCIA)
AND S.DT_CADASTRO BETWEEN to_date('21/04/2014', 'dd/MM/yyyy') AND to_date('09/06/2014', 'dd/MM/yyyy')
AND O.DT_OCORRENCIA BETWEEN to_date('10/05/2014','dd/MM/yyyy') AND to_date('20/05/2014','dd/MM/yyyy')
AND S.cd_tipo_operacao in
(-1, 27, 11, 13, 37, 6, 7, 21, 12, 36, 28, 4, 5)
-- order by using linq?
ORDER BY CLI.NM_APELIDO,
TRANS.NM_APELIDO,
O.DT_OCORRENCIA,
DS_TIPO_OCORRENCIA
这是我的执行计划:
PS:我对sql tunnig一无所知:(
答案 0 :(得分:0)
您可以将一些WHERE条件移动到JOIN条件,因为您在这些表上执行INNER JOIN,如下所示。然后,当您进入LEFT JOIN条件时,您将在较小的数据集上运行。
SELECT
O.DT_OCORRENCIA,
S.NU_SMP,
CLI.NM_APELIDO CLI,
TRANS.NM_ENTIDADE TRANS,
TPO.DS_TIPO_OCORRENCIA,
O.DS_OCORRENCIA,
REPLACE(FNC_RETORNA_MOTORISTAS(S.CD_SMP), '<br>', ';') AS NOME_MOTORISTA,
OG.DS_NOME AS DS_NOME_ORIGEM,
DG.DS_NOME AS DS_NOME_DESTINO,
U.NM_LOGIN AS DS_USUARIO_OCORRENCIA,
CASE
WHEN O.CD_USUARIO_INFORMOU = 717 THEN
'NAO'
ELSE
'SIM'
END FL_MANUAL,
CASE
WHEN (O.FL_ENVIOU_EMAIL_CLIENTE = 'S' OR O.FL_ENVIOU_EMAIL_TRANSP = 'S') THEN
'SIM'
ELSE
'NÃO'
END ENVIOU_EMAIL,
DECODE(O.NU_LOCAL_OCORRENCIA,
'1',
'Origem',
'2',
'Em transito',
'3',
'Alvos',
'4',
'Indiferente') DS_LOCAL_OCORRENCIA,
TOPER.DS_TIPO_OPERACAO
FROM TB_SMP S
INNER JOIN TB_OCORRENCIA O
ON O.CD_SMP = S.CD_SMP
AND S.DT_CADASTRO BETWEEN to_date('21/04/2014', 'dd/MM/yyyy') AND to_date('09/06/2014', 'dd/MM/yyyy')
AND O.DT_OCORRENCIA BETWEEN to_date('10/05/2014','dd/MM/yyyy') AND to_date('20/05/2014','dd/MM/yyyy')
AND S.cd_tipo_operacao in
(-1, 27, 11, 13, 37, 6, 7, 21, 12, 36, 28, 4, 5)
INNER JOIN TB_TIPO_OCORRENCIA TPO
ON O.CD_TIPO_OCORRENCIA = TPO.CD_TIPO_OCORRENCIA
LEFT JOIN TB_TIPO_OPERACAO TOPER
ON TOPER.CD_TIPO_OPERACAO = S.CD_TIPO_OPERACAO
LEFT JOIN TB_USUARIO U
ON U.CD_USUARIO = O.CD_USUARIO_INFORMOU
LEFT JOIN TB_ENTIDADE CLI
ON CLI.CD_ENTIDADE = S.CD_ENTIDADE_CLIENTE
LEFT JOIN TB_ENTIDADE TRANS
ON TRANS.CD_ENTIDADE = S.CD_ENTIDADE_TRANSPORTADOR
LEFT JOIN TB_PONTO_GEOREFERENCIADO OG
ON OG.CD_PONTO_GEOREFERENCIADO = S.CD_PONTO_GEO_ORIGEM
LEFT JOIN TB_PONTO_GEOREFERENCIADO DG
ON (S.CD_PONTO_GEO_DESTINO IS NULL AND
DG.CD_PONTO_GEOREFERENCIADO =
FNC_GET_ULTIMA_ENTREGA_PONTO(S.CD_SMP))
OR (S.CD_PONTO_GEO_DESTINO IS NOT NULL AND
DG.CD_PONTO_GEOREFERENCIADO = S.CD_PONTO_GEO_DESTINO)
-- order by using linq?
ORDER BY CLI.NM_APELIDO,
TRANS.NM_APELIDO,
O.DT_OCORRENCIA,
DS_TIPO_OCORRENCIA;
在用于加入/过滤的列上添加索引也会有所帮助,尤其是在
上TB_SMP.DT_CADASTRO
TB_SMP.cd_tipo_operacao
TB_OCORRENCIA.DT_OCORRENCIA
TB_ENTIDADE.CD_ENTIDADE