繁体   English   中英

验证Oracle查询的优化

[英]Validating optimization of an Oracle query

好的,所以我正在工作这个(相当旧的)项目,该项目使用对Oracle数据库的查询负载。 我最近偶然发现了这颗宝石,它大约需要运行6-7个小时 ,并返回约1400行。 有问题的表/视图包含约200'000行。 我认为这可能花费了比合理时间更长的时间,所以我开始仔细研究一下。 现在,出于安全性/专有性原因,我无法共享确切的查询,但这应该以更笼统的方式显示查询的作用:

SELECT
    some_field,
    some_other_field
FROM (
    SELECT
        *
    FROM
        some_view a
    WHERE
        some_criteria AND
        a.client_no || ':' || a.engagement_no || ':' || a.registered_date = (
            SELECT
                b.client_no || ':' || b.engagement_no || ':' || MAX(b.registered_date)
            FROM
                some_view b
                JOIN some_engagement_view e
                    ON e.client_no = b.client_no AND e.engagement_no = b.engagement_no
                JOIN some_client_view c
                    ON c.client_no = b.client_no
            WHERE
                some_other_criteria AND
                b.client_no = a.client_no AND
                b.engagement_no = a.engagement_no
            GROUP BY
                b.client_no,
                b.engagement_no
        )
);

据我设法弄清楚,基本上应该做的是从some_view(包含对客户/参与度的评估)中获取每个唯一客户/参与度的最新评估。

此处有两个联接,以确保客户和参与存在于另一个系统中,在该系统中完成评估后,将主要处理它们。

注意,它是如何连接两个数字和一个日期,然后将其与子查询进行比较的? “有趣”的设计选择。 因此,我认为,如果用适当的比较替换串联,则至少可以获得某种性能提升。 请注意,我主要开发.NET和Web,并且在数据库方面还远非专家,但我将其重写如下:

SELECT
    some_field,
    some_other_filed
FROM
    some_view a
WHERE
    some_criteria AND
    (a.client_no, a.engagement_no, a.registered_date) = (
        SELECT
            b.client_no,
            b.engagement_no,
            MAX(b.registered_date)
        FROM
            some_view b
            JOIN some_engagement_view e
                ON e.client_no = b.client_no AND e.engagement_no = b.engagement_no
            JOIN some_client_view c
                ON c.client_no = b.client_no
        WHERE
            some_other_criteria AND
            b.client_no = a.client_no AND
            b.engagement_no = a.engagement_no
        GROUP BY
            b.client_no,
            b.engagement_no
    )
);

现在,如果我将第一个选择中的字段替换为COUNT(1) ,则两个查询的行数完全相同,因此是一个很好的开始。 新查询以最快的速度获取数据,时间少于10秒。 旧查询将在大约20秒内获得计数,并且正如我之前提到的,数据需要将近6到7个小时。 它当前正在运行,以便我可以进行某种分析以查看新查询是否有效,但是我想我也想在这里询问是否发现我做的任何明显错误?

编辑还删除了最外面的查询,这似乎并没有实现任何目的,只是使查询看起来更酷..或者其他..我不知道。

扩展我的评论...如果我尝试使用内置视图复制您的查询结构,它也会运行很长时间。 例如,为每个所有者获取最新创建的表(纯粹出于演示目的,可以更简单地完成),这需要几分钟的时间,无论使用哪种版本:

SELECT
    owner,
    object_name
FROM
    all_objects a
WHERE
    (a.owner, a.object_type, TRUNC(a.created)) = (
        SELECT
            b.owner, b.object_type, TRUNC(MAX(b.created))
        FROM
            all_objects b
            JOIN all_tables e
                ON e.owner = b.owner and e.table_name = b.object_name
            JOIN all_users c
                ON c.username = b.owner
        WHERE
            b.owner = a.owner AND
            b.object_type = a.object_type
        GROUP BY
            b.owner,
            b.object_type
    );

如果我重写它以避免使用all_objects (在您的示例中为some_view )进行自some_view ,则改为使用解析函数

SELECT
    owner,
    object_name
FROM (
    SELECT
        a.owner,
        a.object_name,
        row_number() over (partition by a.owner, a.object_type
            order by a.created desc) as rn
    FROM
        all_objects a
        JOIN all_tables e
            ON e.owner = a.owner and e.table_name = a.object_name
        JOIN all_users c
            ON c.username = a.owner
    )
WHERE
    rn = 1;

...然后需要几秒钟。

现在,在这种情况下,我不会因为我有在同一时间产生(在同一秒内尽可能多的对象得到完全相同的输出created而言)。

我当然不知道您的registered_date中存储的值的精度。 因此,您可能需要查看不同的函数,可能是rank而不是row_number ,或者在必要时调整顺序以处理联系。

        rank() over (partition by a.owner, a.object_type
            order by trunc(a.created) desc) as rn
...
WHERE
    rn = 1;

给我相同的结果(嗯,几乎;连接到all_tables也使事情歪斜,因为我似乎在all_objects中列出的表不在all_tables ,但这是附带问题)。 或者max也可以工作:

        max(created) over (partition by a.owner, a.object_type) as mx
...
WHERE
    TRUNC(created) = TRUNC(mx)

在这两种方法中,我都使用trunc在同一天获取所有内容; 如果您的registered_date没有时间部分,则可能不需要。

但是,当然,请检查您是否确实获得了相同的结果。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM