Sql 提高select语句的性能
我有一个选择性能问题,如何使这个SQL更有效Sql 提高select语句的性能,sql,oracle,sql-tuning,Sql,Oracle,Sql Tuning,我有一个选择性能问题,如何使这个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_NO
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
我的执行计划如下:
注:我对sql tunnig一无所知:在对这些表进行内部联接时,可以将一些WHERE条件移动到联接条件,如下所示。然后,在左边的连接条件下,您将在较小的数据集上操作
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;
您可以删除WHERE EXISTS从TB_TIPO_OCORRENCIA T中选择1,其中T.CD_TIPO_OCORRENCIA=O.CD_TIPO_OCORRENCIA,因为您已经在较早的时候内部加入TB_OCORRENCIA和TB_TIPO_OCORRENCIA。Oracle是否将时间存储为日期类型的一部分?然后要避免“是”,这适用于具有连续范围类型的所有系统。我很好奇您是否可以按顺序将DS_TIPO_OCORRENCIA切换到O.DS_OCORRENCIA。同一个表通常意味着使用索引的可能性更大。。。。我通常建议只将这些条件移动到直接引用该表的联接。当表格位于FROM子句中时,在WHERE子句中保留仅引用该表格的条件。对于BETWEEN条件,RDBMS可能会自动执行此操作,因此在这种情况下可能不会获得任何好处。对于内部联接,条件是在on子句中还是在where子句中应该有所不同。Oracle优化器做得相当好。
TB_SMP.DT_CADASTRO
TB_SMP.cd_tipo_operacao
TB_OCORRENCIA.DT_OCORRENCIA
TB_ENTIDADE.CD_ENTIDADE