好的,所以我正在研究这个(相当老的)项目,它使用大量查询来访问 Oracle 数据库。我最近偶然发现了这个 gem,它需要大约 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
)
);
现在,如果我用 a 替换第一个 select 中的字段COUNT(1)
,我会得到两个查询完全相同的行数,所以这是一个好的开始。新查询获取数据的速度与计数一样快,< 10 秒。旧查询在约 20 秒内获得计数,正如我之前提到的,数据需要接近 6-7 小时。它目前正在运行,以便我可以进行某种分析以查看新查询是否有效,但我想我也会在这里问一下,看看我是否有任何明显的错误?
编辑还删除了最外面的查询,它似乎没有实现任何目的,除了可能使查询看起来更酷..或其他什么..我不知道..