Thread: Query planner problem
Okay, I've got two queries that I think the planner should reduce to be logically equivalent but it's not happening. The example queries below have been simplified as much as possible while still producing the problem. What I'm trying to do is create a single prepared statement that can handle null parameters rather than have to dynamically generate the statement in my app code based on supplied parameters. Basically the date constants below would be substituted with parameters supplied on a web search form (or nulls). Here is the query and EXPLAIN that runs quickly: SELECT case_id FROM case_data WHERE case_filed_date > '2004-09-16' AND case_filed_date < '2004-09-20' QUERY PLAN ------------------------------------------------------------- Index Scan using case_data_case_filed_date on case_data (cost=0.00..13790.52 rows=3614 width=18) Index Cond: ((case_filed_date > '2004-09-16'::date) AND (case_filed_date < '2004-09-20'::date)) And here is the query and EXPLAIN from the version that I believe the planner should reduce to be logically equivalent: SELECT case_id FROM case_data WHERE (('2004-09-16' IS NULL) OR (case_filed_date > '2004-09-16')) AND (('2004-09-20' IS NULL) OR (case_filed_date < '2004-09-20')) QUERY PLAN ------------------------------------------------------------- Seq Scan on case_data (cost=0.00..107422.02 rows=27509 width=18) Filter: ((('2004-09-16' IS NULL) OR (case_filed_date > '2004-09-16'::date)) AND (('2004-09-20' IS NULL) OR (case_filed_date < '2004-09-20'::date))) I was hoping that the null comparisons would get folded out by the planner relatively cheaply. But as you can see, the first query uses indexes and the second one uses sequence scans, thereby taking much longer. I guess my question is - is there a better way to accomplish what I'm doing in SQL or am I going to have to dynamically generate the statement based on supplied parameters? Thanks, Ryan
On Sat, 2 Oct 2004 08:06 am, Ryan VanMiddlesworth wrote: [snip] > > > Here is the query and EXPLAIN that runs quickly: > SELECT case_id FROM case_data > WHERE case_filed_date > '2004-09-16' > AND case_filed_date < '2004-09-20' > > QUERY PLAN > ------------------------------------------------------------- > Index Scan using case_data_case_filed_date on case_data > (cost=0.00..13790.52 rows=3614 width=18) > Index Cond: ((case_filed_date > '2004-09-16'::date) > AND (case_filed_date < '2004-09-20'::date)) > > > And here is the query and EXPLAIN from the version that I believe the planner > should reduce to be logically equivalent: > SELECT case_id FROM case_data > WHERE (('2004-09-16' IS NULL) OR (case_filed_date > '2004-09-16')) > AND (('2004-09-20' IS NULL) OR (case_filed_date < '2004-09-20')) > > QUERY PLAN > ------------------------------------------------------------- > Seq Scan on case_data (cost=0.00..107422.02 rows=27509 width=18) > Filter: ((('2004-09-16' IS NULL) OR (case_filed_date > '2004-09-16'::date)) > AND (('2004-09-20' IS NULL) OR (case_filed_date < '2004-09-20'::date))) > > > I was hoping that the null comparisons would get folded out by the planner > relatively cheaply. But as you can see, the first query uses indexes and the > second one uses sequence scans, thereby taking much longer. I guess my > question is - is there a better way to accomplish what I'm doing in SQL or am > I going to have to dynamically generate the statement based on supplied > parameters? > The Index does not store NULL values, so you have to do a tables scan to find NULL values. That means the second query cannot use an Index, even if it wanted to. Regards Russell Smith
Ryan VanMiddlesworth <ryan@vanmiddlesworth.org> writes: > And here is the query and EXPLAIN from the version that I believe the planner > should reduce to be logically equivalent: > SELECT case_id FROM case_data > WHERE (('2004-09-16' IS NULL) OR (case_filed_date > '2004-09-16')) > AND (('2004-09-20' IS NULL) OR (case_filed_date < '2004-09-20')) > I was hoping that the null comparisons would get folded out by the planner > relatively cheaply. You could teach eval_const_expressions about simplifying NullTest nodes if you think it's important enough. regards, tom lane
Russell Smith <mr-russ@pws.com.au> writes: > The Index does not store NULL values This is false. Though the fact that NULL values are indexed in postgres doesn't help with this poster's actual problem. -- greg