-
-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Queries on indexed char(n) column in PostgreSQL use sequential scan #1912
Comments
Possible workarounds:
|
Interesting, thanks for that |
FWIW, I ran in to this exact problem, and an additional warning was added to the PostgreSQL wiki's "Don't Do This" list: https://wiki.postgresql.org/wiki/Don%27t_Do_This#Why_not.3F_12 I switched to |
There's a few deeper issues here. The history behind all of this is a bit scattered, so let me give some recap/context here. A very long time ago, Diesel had However, we can't really model those coercions easily in Diesel, due to a combination of limitations of Rust, and our architecture. There's no easy way for us to say We fixed this in #288 by just making varchar a type alias. This was a workaround, not a fix for the root problem. We've since encountered similar issues that cannot use this workaround. Numeric types are a major case where SQL coerces, but we cannot (it's much less common for this to be painful in practice though). Timestamp vs timestamptz is another case where the types coerce between each other, but do not have identical semantics, and our "just use a type alias" solution would not work. However, strings are special. This really does (mostly) work for pretty much all string types. These types all have identical representation (contrary to what some folks believe, using However, this has come back to bite us in a few ways. The first one we encountered was that these coercions do not apply to arrays. You cannot use The second issue we encountered is that With all that said, I still don't really know how we can fix the "root" problem here. The best I've ever come up with is adding explicit casts for this, which at least gives us an out, but would still make splitting up the string types extremely painful. That said, I do still believe that strings are "special", and I think we might be able to improve the situation here for specifically strings. You don't actually have to know the OID of the type you're transmitting in every case, you can also send 0, which means "interpret this as an untyped string literal". That might actually be exactly what we want for bind parameters sent for a string type. (Note: an implementation doing this will not be as simple as just changing the OID of |
Setup
Versions
Feature Flags
Problem Description
My table has a primary key of type
char(11)
. When querying this table, Diesel sends over a parameterized query and a value of typetext
instead ofbpchar
. This forces a slow sequential scan instead of doing an index-only scan. When running a similar query from psql, PostgreSQL uses the index.What are you trying to accomplish?
Find an indexed
char(n)
quicklyWhat is the expected output?
results in tens of milliseconds
What is the actual output?
results in 1+ second
Are you seeing any additional errors?
No
Steps to reproduce
I think all you need to observe this is an indexed
char(n)
column, a.find(
or.filter(id.eq(
in Diesel, andauto_explain
on the server side to confirm sequential scans. But I have a complete test case set up to demonstrate this:For the sake of completeness, I did this on a new Debian 9.5:
then
What should be a quick index lookup instead takes 1 second:
With these postgresql server settings, you can see what is happening on the server side:
(note:
auto_explain
is in thepostgresql-contrib
package on Debian.)When Diesel sends over its parameterized query, PostgreSQL logs a sequential scan:
Run a similar query from
psql
and PostgreSQL logs anIndex Only Scan
:Checklist
closed if this is not the case)
The text was updated successfully, but these errors were encountered: