调整SQL选择

时间:2013-09-02 11:53:32

标签: sql sql-server sql-tuning

我不太了解优化的SQL选择,我的查询非常慢。也许你有一些提示使我的查询更快。

SQL查询

SELECT DISTINCT CLI.FANTASIA AS Cliente
            ,   DBSMP.VEICULO_PLACA AS Placa
            ,   DBSMP.DTINICIOPREV AS 'Data Inicio Previsto'
            ,   DBSMP.DTFIMPREV AS 'Data Fim Previsto'
            ,   DBSMP.DTINICIOREAL AS 'Data Incio Real'
            ,   DBSMP.DTFIMREAL AS 'Data Fim Real'
            ,   DBSMP.CIDADE_DES AS 'Cidade Destino'
            ,   DBSMP.CIDADE_ORI AS 'Cidade Origem'
            ,   TRA.FANTASIA AS Transportador
FROM DBSMP_WORK WORK
INNER JOIN DBSMP ON WORK.ID_SMP = DBSMP.ID_SMP
INNER JOIN DBCLIENTE CLI ON DBSMP.ID_CLIENTE = CLI.ID_CLIENTE
LEFT JOIN DBCLIENTE TRA ON DBSMP.ID_TRANSPORTADOR = CLI.ID_CLIENTE
WHERE WORK.[status] IN ('F')
    AND DBSMP.ID_CLIENTE IN (85, 107, 137, 139, 510, 658, 659, 661, 702)
    AND TRA.RAZAO = 'Google'
    AND DBSMP.DTINICIOPREV BETWEEN '01/01/1900' AND '02/09/2013'

然后,我的问题是:我怎样才能更快地获得上述观点?

此查询必须在SQL Server实例中运行。

提前致谢。

5 个答案:

答案 0 :(得分:3)

只是一些想法:

  • 尽量不要使用DISTINCT,而是限制您的数据。
  • 尽量不要使用IN,例如IN('F')可以是='F'
  • 阅读索引并为您要查询/加入的列
  • 创建索引
  • 阅读如何创建和阅读执行计划以找到瓶颈

答案 1 :(得分:2)

试试这个 -

SELECT DISTINCT CLI.FANTASIA AS Cliente
            ,   DBSMP.VEICULO_PLACA AS Placa
            ,   DBSMP.DTINICIOPREV AS [Data Inicio Previsto]
            ,   DBSMP.DTFIMPREV AS [Data Fim Previsto]
            ,   DBSMP.DTINICIOREAL AS [Data Incio Real]
            ,   DBSMP.DTFIMREAL AS [Data Fim Real]
            ,   DBSMP.CIDADE_DES AS [Cidade Destino]
            ,   DBSMP.CIDADE_ORI AS [Cidade Origem]
            ,   TRA.FANTASIA AS Transportador
FROM (
    SELECT *
    FROM DBSMP
    WHERE DBSMP.DTINICIOPREV BETWEEN '19000101' AND '20130902'
        AND DBSMP.ID_CLIENTE IN (85, 107, 137, 139, 510, 658, 659, 661, 702)
) DBSMP
JOIN DBCLIENTE CLI ON DBSMP.ID_CLIENTE = CLI.ID_CLIENTE
JOIN DBCLIENTE TRA ON DBSMP.ID_TRANSPORTADOR = TRA.ID_CLIENTE -- or TRA.ID_TRANSPORTADOR = CLI.ID_CLIENTE
WHERE TRA.RAZAO = 'Google'
    AND EXISTS(
        SELECT 1 
        FROM DBSMP_WORK WORK
        WHERE WORK.ID_SMP = DBSMP.ID_SMP
            AND WORK.[status] = 'F'
    )

答案 2 :(得分:1)

首先,您不需要最终LEFT JOINTRA.RAZAO = 'Google'子句中的条件为WHERE。这有效地将LEFT JOIN转换为内连接。

但最重要的是join条件:

LEFT JOIN DBCLIENTE TRA ON DBSMP.ID_TRANSPORTADOR = CLI.ID_CLIENTE

换句话说,您的查询没有意义。您正在加入一个没有引用该表的表。我不确定什么是正确的解决方案,因为你没有提供足够的信息。我最好的猜测是,这就是from子句的意思:

FROM DBSMP_WORK WORK 
INNER JOIN DBSMP ON WORK.ID_SMP = DBSMP.ID_SMP
INNER JOIN DBCLIENTE CLI ON DBSMP.ID_CLIENTE = CLI.ID_CLIENTE
LEFT JOIN DBCLIENTE TRA ON TRA.ID_TRANSPORTADOR = CLI.ID_CLIENTE

答案 3 :(得分:0)

确保各个表格中的列ID_SMPID_CLIENTEID_TRANSPORTATOR都有索引。这将使连接操作更快。然后,要完成它,您也可以尝试为STATUS子句中的列RAZAODTINICIOPREVWHERE编制索引。

答案 4 :(得分:-1)

你的M $工具应该有一个查询分析器/ expain工具,它可以显示连接和表达式及其“成本” - 在改进语句时在迭代过程中使用它。

将indizes添加到参与join子句或where子句

的列中

尝试删除所有选定的列并替换为“1”( - > SELECT 1 FROM ..) - 如果数据集太大,这将显示

尝试删除DISTINCT,因为它按值执行昂贵的组