好的,所以我正在研究这个(相当老的)项目,它使用了大量针对Oracle数据库的查询。我最近偶然发现了这个宝石,大约需要6-7小时小时才能运行并返回〜1400行。问题中的表格/视图包含〜200'000行。我觉得这感觉好像比合理的时间稍长一点,所以我开始仔细观察它。现在我不能,出于安全/特殊原因,共享准确的查询,但这应该显示查询确实较一般什么:验证Oracle查询的优化
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和网络,以及当它涉及到数据库的专家很远,但我重写,如下所示:
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小时。它目前正在运行,因此我可以进行某种分析以查看新查询是否有效,但是我认为我也会在此问一下,看看我做了什么明显错误的事情?
编辑还删除了最外面的查询,这似乎并没有履行任何样的目的,除了可能使查询外观更酷..或东西..我不知道..
为避免自己加入'some_view',可能值得考虑[分析函数](http://docs.oracle.com/cd/E11882_01/server.112/e26088/functions004.htm)。但你应该看看解释计划,看看它花费的时间。 –