使用 distinct 和 top 子句执行查询需要更多时间

Posted

技术标签:

【中文标题】使用 distinct 和 top 子句执行查询需要更多时间【英文标题】:query execution taking more time with distinct and top clause 【发布时间】:2019-02-17 11:22:43 【问题描述】:

我有 2 个表与过程中的 union all 运算符相结合。第一个表包含 2000 万条记录,第二个表包含 100 万条记录。 如果我单独使用 Top 子句而没有 distinct 子句,它会给出输出,但是当我将 TOP 子句与 Distinct 子句一起使用时,它会在查询执行后非常快地返回前 800 条记录而没有完成。同时使用两者(Distinct 和 Top ) 在同一个查询中?

SELECT Distinct TOP 1000
            TP.F_PRODUCT AS ID,
            TP.F_PRODUCT_NAME AS [NAME],
            TP.F_LANGUAGE AS LANGCODE,
            TP.F_FORMAT AS FMTCODE,
            TP.F_CUSTOM1 AS TN,
            TP.F_CUSTOM2 AS CP,
        FROM 
            T_PDF TP WHERE TP.F_PRODUCT <>''
    UNION ALL

    SELECT Distinct TOP 1000
            TP.F_PRODUCT AS ID,
            TP.F_PRODUCT_NAME AS [NAME],
            TP.F_LANGUAGE AS LANGCODE,
            TP.F_FORMAT AS FMTCODE,
            TP.F_CUSTOM3 AS TN,
            TP.F_CUSTOM4 AS CP,
        FROM 
            T_html TP WHERE TP.F_PRODUCT <>''

【问题讨论】:

【参考方案1】:

使用TOPDISTINCT 没有任何问题,无论UNION ALL 结构是否存在。如果这就是您需要的数据,那么这就是实现它的方法。

但是,当您请求DISTINCT 时,您需要意识到系统可能必须检查大量记录以确保它获取足够的“原始数据”来获得请求数量的 DISTINCT 值;最坏的情况是它必须运行所有 2000 万条记录! MSSQL 非常擅长利用手头数据的统计信息来猜测它需要多少行。

现在,您的统计数据可能“偏离”,导致系统获取的记录“太少”,从而导致您获得 800 个“快速结果”,但随后需要花费大量时间从桌子。

我建议尝试做两件事:

要求一个估计的计划并学会解释它 更新上述表的统计信息,然后再试一次,看看估计的计划是否改变;尤其是估计的行数应该很有趣

祝你好运, 罗比

PS:请记住,在请求TOP n 时,您将获得整个数据的“随机选择”;无法保证您会从表中获得“第一”行!要到达那里,您需要明确指定ORDER BY 子句,这可能会为查询的执行增加(很多)额外的工作;同样,查询计划将显示这一点。 (您可以同时输入两个查询并要求估计计划以查看差异。也就是说,当一个查询的成本为 10% 和另一个为 90% 时,这并不意味着一个查询的运行速度比另一方面,成本与时间不同,虽然两者之间确实存在联系,但不是线性的)

【讨论】:

正确。现在我在存储过程中的 select 语句非常快地选择了 910 条记录,之后完成执行需要更多时间。我是否必须使用任何 HINT 快速完成执行或任何方法快速挑选前 1000 条记录? 嗯,有FAST 提示,但我不确定这是否是一个很好的匹配。 cf***.com/questions/1308946/…

以上是关于使用 distinct 和 top 子句执行查询需要更多时间的主要内容,如果未能解决你的问题,请参考以下文章

SQL 查询 - 结合 DISTINCT 和 TOP?

第二十九章 SQL命令 DISTINCT

sqlserver分页去重失效

Oracle Distinct子句

在 Django 中使用带有 GROUP BY 子句的 COUNT(DISTINCT 字段)

JDBC WHERE子句条件实例