Oracle 不一致的查询性能行为
Posted
技术标签:
【中文标题】Oracle 不一致的查询性能行为【英文标题】:Oracle inconsistent performance behaviour of query 【发布时间】:2015-03-06 10:11:57 【问题描述】:考虑以下查询:
SELECT *
FROM (
SELECT ARRM.*, ROWNUM
FROM CRS_ARRANGEMENTS ARRM
WHERE
CONCAT(ARRM.NBR_ARRANGEMENT, ARRM.TYP_PRODUCT_ARRANGEMENT) >
CONCAT('0000000000000000', '0000')
ORDER BY
ARRM.NBR_ARRANGEMENT,
ARRM.TYP_PRODUCT_ARRANGEMENT,
ARRM.COD_CURRENCY)
WHERE ROWNUM < 1000;
此查询在具有 10 000 000 个条目的表上运行。从 Oracle SQL Developer 或我的应用程序运行查询时需要 4 分钟才能运行!不幸的是,这也是我正在编写的应用程序内部的行为。将值从 1000 更改为 10 完全没有影响,这表明它正在执行全表扫描。
但是,当从 SQuirreL 运行时,查询会在 几毫秒内返回。这怎么可能?解释在 SQuirreL 中生成的计划给出:
但是对于同一个查询,Oracle SQL Developer 会生成不同的解释计划:
知道这种行为差异是如何产生的吗?我无法理解它。我尝试使用 JPA 和原始 JDBC。在应用程序中,我需要解析所有 10 000 000 条记录,并且此查询用于分页,因此不能选择等待 4 分钟(这需要 27 天)。
注意:我在 SQuirreL 和我的应用程序中使用相同的 Oracle jdbc 驱动程序,因此这不是问题的根源。
【问题讨论】:
执行 SELECT COUNT(*) .... 看看性能差距是否仍然存在。我猜 SQuirrel 没有得到所有的数据。 SQuirreL 确实获得了所有数据,这没有区别。当数据库表中仅加载 100 000 个条目时,没有这种差异。 你看过这个帖子吗:community.oracle.com/thread/945873 可能是绑定变量偷看的问题。 这不是绑定变量窥视,因为查询对相同的变量执行不同。 【参考方案1】:显然,国家语言支持或 NLS 参数与它有关。 Oracle SQL Developer 将它们设置为“荷兰语”,这是基于您的区域设置的默认设置,而 SQuirreL 将其设置为 BINARY。这种差异使得优化器使用不同的路径来解决查询。为了在 jdbc 会话中使用正确的 NLS_SORT 参数,需要使用以下命令:
ALTER SESSION SET NLS_SORT=BINARY
那么正确的索引将被用于查询。
【讨论】:
如果使用基于文本的解释计划,这些问题更容易找到。explain plan for select ...
然后select * from table(dbms_xplan.display);
将在Notes
部分显示差异。出于某种原因,我曾经使用过的每个 IDE 都试图使解释计划“漂亮”,但未能包含关键信息。
我也这样做了@JonHeller,但关于 ns_sort 的信息也不包括在内。花了 12 个小时与 oracle 社区论坛的人一起寻找问题,所以这不是一件简单的事情。以上是关于Oracle 不一致的查询性能行为的主要内容,如果未能解决你的问题,请参考以下文章