2

我对优化的 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 实例中运行。

提前致谢。

4

5 回答 5

3

只是一些想法:

  • 尽量不要使用DISTINCT,而是适当限制您的数据。
  • 尽量不要用IN,比如IN('F')可以='F'
  • 阅读索引并为您正在查询/加入的列创建它们
  • 阅读如何创建和阅读执行计划以找到瓶颈
于 2013-09-02T12:00:49.683 回答
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'
    )
于 2013-09-02T12:42:56.603 回答
1

首先,您不需要 final LEFT JOIN。您TRA.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
于 2013-09-02T12:01:39.923 回答
0

确保您在各个表中的列ID_SMP, ID_CLIENTE,上有索引。ID_TRANSPORTATOR这将使连接操作更快。然后,要完成它,您可以尝试索引列STATUSRAZAO也可以DTINICIOPREVWHERE子句中。

于 2013-09-02T11:59:36.673 回答
-1

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

将索引添加到参与连接子句或 where 子句的列

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

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

于 2013-09-02T12:02:16.160 回答