I have the following table(s):
CREATE TABLE items (
id NUMBER(20, 0) NOT NULL PRIMARY KEY,
assigned_to NUMBER(20, 0) DEFAULT NULL NULL,
revision NUMBER(10, 0) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
created_by NUMBER(20, 0) DEFAULT NULL NULL,
updated_at TIMESTAMP DEFAULT NULL NULL,
updated_by NUMBER(20, 0) DEFAULT NULL NULL );
CREATE TABLE item_details (
item_id NUMBER(20, 0) NOT NULL PRIMARY KEY,
item_created_date TIMESTAMP NOT NULL,
item_name VARCHAR2(255) DEFAULT NULL NULL,
item_note VARCHAR2(255) DEFAULT NULL NULL );
CREATE TABLE users (
id NUMBER(20, 0) NOT NULL PRIMARY KEY,
email VARCHAR2(255) DEFAULT NULL NULL );
CREATE TABLE items_mv AS
SELECT i.id,
i.assigned_to,
d.item_created_date,
d.item_name,
d.item_note
FROM items i,
item_detail d
WHERE d.item_id = d.id
AND d.item_created_date IS NOT NULL;
CREATE INDEX item_created_date_idx ON items_mv (item_created_date, id);
and the following query:
SELECT i.*,
d.*,
u.id AS ass_to_id,
u.email AS ass_to_email,
NULL AS cre_by_id,
NULL AS upd_by_id
FROM ( SELECT id,
item_some_date
FROM ( SELECT i.id,
i.item_created_date
FROM items_mv i
ORDER BY item_created_date DESC, id DESC
)
FETCH NEXT :limit ROWS ONLY
) items_table
JOIN items i ON i.id = items_table.id
JOIN item_details d ON i.id = d.item_id
ORDER BY d.item_created_date DESC, d.item_id DESC;
which runs fine through DataGrip on Oracle, with the expected query plan. However, on production, when called through Spring Boot application with NamedParameterJdbcTemplate
as follows:
getNamedParameterJdbcTemplate().query(findQuery, new HashMap(){{
put("limit", 11);
}}, myResultSetExtractor);
It generates a different SQL id from the one I'm running from DataGrip and takes too long, never finishes. There are +20m rows in items table. I've also tried to use index hint /*+INDEX(items_mv item_created_date_idx)*/
to no luck. What am I missing?
Update:
Replacing the :limit
in SQL String in Java, basically, embedding the limit fixes the issue, speeding up the query with the correct/fast SQL ID. Making NamedParameterJdbcTemplate
run with the correct parameter type:
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("limit", limit, Types.NUMERIC);
getNamedParameterJdbcTemplate().query(findQuery, params, myResultSetExtractor);
does not run the fast query. I think it's Oracle not picking up the correct execution plan/index when wrong parameter types are involved. What'd be the correct type for my limit
parameter that's used in FETCH NEXT :limit ROWS ONLY
?