Reputation: 2233
Is there a significant difference in postgresql's execution, performance, or logic between
SELECT "users".* FROM "users" WHERE ("users"."deleted_at" IS NULL)
and
SELECT "users".* FROM "users" WHERE (NOT ("users"."deleted_at" IS NOT NULL))
Obviously, if written by hand, the first expression is the one I would write (who would intentionally write a double negative?!). But in this case, I'm using ruby's arel library to dynamically create both versions, sort of like so:
def generate_query(search_terms, negated=false, users=User)
where_clause = arel_for_one_of_many_possible_queries(search_terms)
where_clause = where_clause.not if negated
users.where(where_clause)
end
And, for the "deleted"
search_term, the where_clause
will be arel_table[:deleted_at].not_eq(nil)
, but for other search_terms it could be a variety of clauses, including compound clauses and subselects. Adding the .not
to the end, arel will always generate SQL of the second form. I could generate the first form by special casing my NULL
checks and manually generating .eq
or .not_eq
as the case may be, but I'd want some clear benefit to doing that before I make my code more verbose.
Upvotes: 4
Views: 214
Reputation: 127406
Use EXPLAIN to see the difference, if there is any.
I think the query rewriter will optimize this, but I didn't check the source code for this example.
Edit: I was wrong, this is not optimized at all. Where ("users"."deleted_at" IS NULL) can use an index, the (NOT ("users"."deleted_at" IS NOT NULL)) condition results in a sequential disk scan.
Upvotes: 7