Index will be used if you remove cast to date (joined_date
instead of joined_date::date
) from WHERE
clause (upper bound in BETWEEN
should be changed accordingly).
select *
from test
where joined_date >= '2017-09-25' AND joined_date <'2017-10-26' ;
Alternatively , you can create index as
CREATE INDEX index_test2 ON test (cast (joined_date as date), company_name, department);
Proof
CREATE TABLE test (
id serial PRIMARY KEY,
company_name varchar(255) not null,
department varchar(255) not null,
joined_date timestamp not null
);
INSERT INTO test(company_name, department,joined_date)
SELECT
md5(x::text),
CASE WHEN x%2 = 0 THEN 'foo' WHEN x%3 = 0 THEN 'bar' ELSE 'baz' END,
now()
FROM generate_series(1,1e6)
AS gs(x);
CREATE INDEX index_test
ON test (joined_date, company_name, department);
VACUUM ANALYZE test;
Query 1
EXPLAIN ANALYZE SELECT *
FROM test
WHERE joined_date BETWEEN '2017-09-25' AND '2017-10-25';
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------------
Index Scan using index_test on test (cost=0.42..8.45 rows=1 width=49) (actual time=0.069..0.069 rows=0 loops=1)
Index Cond: ((joined_date >= '2017-09-25 00:00:00'::timestamp without time zone) AND (joined_date <= '2017-10-25 00:00:00'::timestamp without time zone))
Planning time: 0.142 ms
Execution time: 0.097 ms
(4 rows)
Query 2
EXPLAIN ANALYZE SELECT *
FROM test
WHERE joined_date BETWEEN '2017-09-25' AND '2017-10-25'
AND company_name = 'xxx';
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Index Scan using index_test on test (cost=0.42..8.45 rows=1 width=49) (actual time=0.016..0.016 rows=0 loops=1)
Index Cond: ((joined_date >= '2017-09-25 00:00:00'::timestamp without time zone) AND (joined_date <= '2017-10-25 00:00:00'::timestamp without time zone) AND ((company_name)::text = 'xxx'::text))
Planning time: 0.111 ms
Execution time: 0.047 ms
(4 rows)
Query 3
SELECT *
FROM test
WHERE joined_date BETWEEN '2017-09-25' AND '2017-10-25'
AND company_name = 'xxx'
AND department = 'yyy';
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Index Scan using index_test on test (cost=0.42..6.20 rows=1 width=49) (actual time=0.017..0.017 rows=0 loops=1)
Index Cond: ((joined_date >= '2017-09-25 00:00:00'::timestamp without time zone) AND (joined_date <= '2017-10-25 00:00:00'::timestamp without time zone) AND ((company_name)::text = 'xxx'::text) AND ((department)::text = 'yyy'::text))
Planning time: 0.120 ms
Execution time: 0.046 ms
(4 rows)
varchar(255)
in PostgreSQL, just usetext
. also, don't usetimestamp
usetimestamp with time zone