SQL 百分位数计算运行非常缓慢 - 需要帮助加快速度

Posted

技术标签:

【中文标题】SQL 百分位数计算运行非常缓慢 - 需要帮助加快速度【英文标题】:SQL percentile calculation running very slowly - need help speeding it up 【发布时间】:2017-09-17 19:21:33 【问题描述】:

我有一个大表(目前大约有 8.5 亿行),并且需要每周计算百分位值,因为插入了新数据并且静态数据变脏了。但是,该过程非常慢(我的硬件/当前查询需要 5-6 小时)。

如何更改我的查询以加快查询速度?

现在,我的查询基本上是这样的:

SELECT DISTINCT [ident1]
    ,[ident2]
    ,[ident3]
    ,[ident4]
    ,percentile_cont(0.05)
        WITHIN GROUP (
            ORDER BY [value] ASC
        ) OVER (
            PARTITION BY [ident1]
                ,[ident2]
                ,[ident3]
                ,[ident4]
        ) AS [percentile_5]
    ,percentile_cont(0.10)
        WITHIN GROUP (
            ORDER BY [value] ASC
        ) OVER (
            PARTITION BY [ident1]
                ,[ident2]
                ,[ident3]
                ,[ident4]
        ) AS [percentile_10]
    ,percentile_cont(0.25)
        WITHIN GROUP (
            ORDER BY [value] ASC
        ) OVER (
            PARTITION BY [ident1]
                ,[ident2]
                ,[ident3]
                ,[ident4]
        ) AS [percentile_25]
    ,percentile_cont(0.50)
        WITHIN GROUP (
            ORDER BY [value] ASC
        ) OVER (
            PARTITION BY [ident1]
                ,[ident2]
                ,[ident3]
                ,[ident4]
        ) AS [percentile_50]
    ,percentile_cont(0.75)
        WITHIN GROUP (
            ORDER BY [value] ASC
        ) OVER (
            PARTITION BY [ident1]
                ,[ident2]
                ,[ident3]
                ,[ident4]
        ) AS [percentile_75]
    ,percentile_cont(0.90)
        WITHIN GROUP (
            ORDER BY [value] ASC
        ) OVER (
            PARTITION BY [ident1]
                ,[ident2]
                ,[ident3]
                ,[ident4]
        ) AS [percentile_90]
    ,percentile_cont(0.95)
        WITHIN GROUP (
            ORDER BY [value] ASC
        ) OVER (
            PARTITION BY [ident1]
                ,[ident2]
                ,[ident3]
                ,[ident4]
        ) AS [percentile_95]
FROM dataTable

认为问题的一部分是,如果没有DISTINCT 选择,我在数据库中的每个值都会得到一行。 SQL 是否足够聪明,可以只为每个组计算一次百分位数?还是对每个值重复计算?

任何帮助将不胜感激。

【问题讨论】:

你需要 percentile_cont 还是可以使用 percentile_disc 执行计划告诉您有关此查询的什么信息? (首先要看的地方应该是执行计划。)例如,它可能会识别缺失的索引。 我正在制定执行计划。我的 DBA 目前禁用了该功能。与此同时,索引这个的最佳方法是什么? [ident1]、[ident2]、[ident3]、[ident4] 和 [value] 上的聚集索引?或者可能是列的某个子集? 【参考方案1】:

将 distinct 放入子查询中:

select . . .
from (select distinct . . . ) s;

distinct 应该在 计算完所有 select 列之后发生。

【讨论】:

这不会改变执行计划,Windowed Aggregates 是在 before distinct 计算的 @dnoeth 。 . .确切地。如果给定行有 100 个副本,它们将被计算 100 次。据推测,OP 在应用 distinct 后想要窗口函数值。 但是百分位数通常是在完整的数据集上计算的,事先应用 DISTINCT 可能会改变结果。 @dnoeth 。 . .我发现我使用select distinct 的实例很少,而没有窗口函数的实例。我只能模糊地猜测 OP 可能真正想要什么。 SQL Server 只实现了Window版本,但是OP想要Aggregate版本percentile_cont(0.05) WITHIN GROUP ( ORDER BY [value] ASC ) ... GROUP BY [ident1] ,[ident2] ,[ident3] ,[ident4]

以上是关于SQL 百分位数计算运行非常缓慢 - 需要帮助加快速度的主要内容,如果未能解决你的问题,请参考以下文章

Python模拟显示性能缓慢,如何加快数组计算

在 BigQuery 中计算百分位数

sql 计算Postgresql中的百分位数

根据 SQL 中的日期计算百分位数

如何计算列的每个值所在的百分位数? (Spark SQL)[重复]

在 SQL 中分析并形成分位数并计算落在各个分位数中的值的百分比