考虑以下查询:
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;
此查询在具有10000000条目的表上运行。从Oracle SQL Developer或我的应用程序运行查询时,需要4分钟才能运行!不幸的是,这也是我正在编写的应用程序内部的行为。将该值从1000更改为10完全没有影响,表明它正在执行全表扫描。
但是,从SQuirreL运行时,查询将在几毫秒内返回。那怎么可能?在SQuirreL中生成的解释计划给出:
但是对于相同的查询,Oracle SQL Developer中会生成一个不同的解释计划:
知道这种行为差异怎么可能吗?我无法理解。我尝试使用JPA和原始JDBC。在应用程序中,我需要解析所有10000000条记录,并且此查询用于分页,因此等待4分钟不是一个选择(这将花费27天)。
注意:我在SQuirreL和我的应用程序中使用相同的Oracle jdbc驱动程序,因此这不是问题的根源。
最佳答案
显然,国家语言支持或NLS参数与它有关。 Oracle SQL Developer将它们设置为“ Dutch”,这是基于您的语言环境的默认设置,而SQuirreL则将其设置为BINARY。这种差异使优化器使用不同的路径来解决查询。为了在jdbc会话中使用正确的NLS_SORT参数,需要使用以下命令:
ALTER SESSION SET NLS_SORT=BINARY
然后将在查询上使用正确的索引。