Oracle inconsistent performance behaviour of query

2019-08-07 05:20发布

问题:

Consider the following query:

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;

This query runs on a table that has 10 000 000 entries. When running the query from Oracle SQL Developer or my application it takes 4 minutes to run! Unfortunately that is also the behaviour inside the application that I'm writing. Changing the value from 1000 to 10 has no impact at all, suggesting that it is doing a full table scan.

However when running from SQuirreL the query returns within a few milliseconds. How is that possible? Explain plan generated in SQuirreL gives:

But a different explain plan is generated in Oracle SQL Developer, for the same query:

Any idea how this difference in behaviour is possible? I can't get to understand it. I tried with JPA and raw JDBC. In the application I need to parse through all 10 000 000 records and this query is used for the paging, so waiting 4 minutes is not an option (that would take 27 days).

Note: I'm using the same Oracle jdbc driver in SQuirreL and my application so that is not the source of the problem.

回答1:

Apparently the National Language Support or NLS parameters had something to do with it. Oracle SQL Developer had them set to "Dutch", default setting based on your Locale, while SQuirreL has it set to BINARY. This difference made the optimizer use different paths to solve the query. In order to use the correct NLS_SORT parameter in the jdbc session the following command needs to be used:

ALTER SESSION SET NLS_SORT=BINARY

Then the correct indexes will be used on the query.