Home » RDBMS Server » Performance Tuning » INDEXES on TIMESTAMP (Oracle 11.2 WIndows Vista 64bit)
INDEXES on TIMESTAMP [message #500079] Thu, 17 March 2011 12:01
amcghie
Messages: 35
Registered: March 2005
Location: Sunny Dubai
Member
When performing a SELECT statement using a TIMESTAMP column in the WHERE predicate (which has been indexed), why does the optimiser not use an index (i.e performs a Full Table scan) when using the TO_TIMESTAMP function, yet performs a range scan on the index when using the TO_TIMESTAMP value in an in-line view. See the script below to replicate the issue.
-- Create a new table for the test
CREATE TABLE order_test
  ( order_id      NUMBER(9)                NOT NULL
  , order_date    TIMESTAMP                NOT NULL
  , order_date_tz TIMESTAMP WITH TIME ZONE NOT NULL );  
  
-- Create a sequence for the test
CREATE SEQUENCE order_id_seq 
  START WITH 1;

DECLARE
  l_timestamp TIMESTAMP;
BEGIN
  -- Create some data spread over the past 3 years
  FOR l_index IN 1..2000000 LOOP
    --
    l_timestamp := SYSTIMESTAMP - NUMTODSINTERVAL(1+ABS(MOD(dbms_random.random, 365*3)));
    --
    INSERT INTO order_test
      ( order_id, order_date, order_date_tz )
    VALUES
      ( order_id_seq.NEXTVAL, l_timestamp, l_timestamp );
    --
  END LOOP;
  --
END;
/

-- Create a index on the order_date columns
CREATE INDEX order_test_idx1 ON order_test ( order_date );
CREATE INDEX order_test_idx2 ON order_test ( order_date_tz );

-- Ensure that there is a nice spread of data
SELECT TO_CHAR(order_date, 'YYYY-Q'), COUNT(1)
FROM    order_test
GROUP BY TO_CHAR(order_date, 'YYYY-Q')
ORDER BY 1;

DELETE FROM plan_table;

-- Index ORDER_TEST_IDX1 is NOT hit using the TO_TIMESTAMP function
EXPLAIN PLAN 
SET statement_id = 'order_date'
FOR
  SELECT * 
  FROM   order_test
  WHERE  order_date >= TO_TIMESTAMP('01-JUN-2010','DD-MON-YYYY') 
  AND    order_date  < TO_TIMESTAMP('01-JAN-2011','DD-MON-YYYY');

SELECT plan_table_output 
FROM   table(dbms_xplan.display('plan_table',null,'serial'));

-- Repeat the query using the TIMESTAMP WITH TIME ZONE column
-- Index ORDER_TEST_IDX2 is hit
EXPLAIN PLAN
SET statement_id = 'order_date_tz'
FOR
  SELECT * 
  FROM   order_test
  WHERE  order_date_tz > TO_TIMESTAMP('01-OCT-2010','DD-MON-YYYY')
  AND    order_date_tz < TO_TIMESTAMP('01-JAN-2011','DD-MON-YYYY');

SELECT plan_table_output 
FROM   table(dbms_xplan.display('plan_table',null,'serial'));


-- Re-execute the query using the TIMESTAMP column but using an in-line view
-- Index ORDER_TEST_IDX1 is now hit
EXPLAIN PLAN
SET statement_id = 'order_date_inline'
FOR
  SELECT * 
  FROM   order_test 
  WHERE  order_date < ( SELECT TO_TIMESTAMP('01-JAN-2011','DD-MON-YYYY') FROM dual )
  AND    order_date > ( SELECT TO_TIMESTAMP('01-OCT-2010','DD-MON-YYYY') FROM dual );

SELECT plan_table_output 
FROM   table(dbms_xplan.display('plan_table',null,'serial'));

-- Create a simple function that takes a TIMESTAMP and RETURNS a TIMESTAMP
CREATE OR REPLACE FUNCTION cast_timestamp(i_timestamp IN TIMESTAMP)
  RETURN TIMESTAMP
IS
BEGIN
  RETURN i_timestamp;
END cast_timestamp;
/

-- Re-execute the query passing the TIMESTAMP into the CAST_TIMESTAMP function
-- Index ORDER_TEST_IDX1 is also hit
EXPLAIN PLAN
  SET statement_id = 'order_date_func'
  FOR
  SELECT * 
  FROM   order_test 
  WHERE  order_date > cast_timestamp(TO_TIMESTAMP('01-OCT-2010','DD-MON-YYYY'))
  AND    order_date < cast_timestamp(TO_TIMESTAMP('01-JAN-2011','DD-MON-YYYY'));

SELECT plan_table_output 
FROM   table(dbms_xplan.display('plan_table',null,'serial'));



Any advice would be greatly appreciated

Cheers

Andy
Previous Topic: help me tune this
Next Topic: 9582.69043 gigabytes of physical read total bytes and increasing!
Goto Forum:
  


Current Time: Fri Apr 19 20:50:17 CDT 2024