We are having trouble when querying a table in our production database. One text column will compare equal to a string we filter on in the where clause, but postgres will not select the row. (We are on postgres 11.11) Our table set up like this:
(PROD)=> \d names;
Table "public.names"
Column | Type | Collation | Nullable | Default
----------------------+-----------------------------+-----------+----------+---------
name | text | | not null |
processed_name | text | | not null |
name_index | integer | | not null |
when_created | timestamp without time zone | | not null |
Indexes:
"names_pkey" PRIMARY KEY, btree (name, processed_name)
"names_name_index_key" UNIQUE CONSTRAINT, btree (name_index)
"ix_names_name" btree (name)
"ix_names_processed_name" btree (processed_name)
When we process a list of names we check if they are already in the table in order to prevent double adding and violating the primary key constraint.
However on one name, 'Сергей Иванович МЕНЯЙЛО', the query to see if the name is already present returns an empty set
I would expect to get back the row with the same name. However when we attempt to insert the row in the table we get a primary key conflict
Here are some queries which might explain the problem better
(PROD)=> SELECT name_index,
name,
name = 'Сергей Иванович МЕНЯЙЛО' names_compare_equal
FROM names where name_index = 75128;
name_index | name | names_compare_equal
----------------------+-------------------------+---------------------
75128 | Сергей Иванович МЕНЯЙЛО | t
(1 row)
However filtering instead on the name column selects no rows.
2021-05-24 20:37:41 UTC
(PROD)=> SELECT name_index,
name,
name = 'Сергей Иванович МЕНЯЙЛО'
names_compare_equal
FROM names
WHERE name = 'Сергей Иванович МЕНЯЙЛО';
name_index | name | names_compare_equal
----------------------+------+---------------------
(0 rows)
So then if we try and insert the row we get a primary key conflict:
(PROD)>=> INSERT INTO names (name_index, name, processed_name, when_created)
VALUES (89266, 'Сергей Иванович МЕНЯЙЛО', lower('Сергей Иванович МЕНЯЙЛО'), now());
ERROR: duplicate key value violates unique constraint "names_pkey"
DETAIL: Key (name, processed_name)=(Сергей Иванович МЕНЯЙЛО, сергей иванович меняйло) already exists.
What's more, if I query based on the hash of the rows I get the correct result:
(PROD)=> SELECT name_index,
name,
name = 'Сергей Иванович МЕНЯЙЛО' names_compare_equal
FROM names
WHERE md5(name) = md5('Сергей Иванович МЕНЯЙЛО');
name_index | name | names_compare_equal
----------------------+-------------------------+---------------------
75128 | Сергей Иванович МЕНЯЙЛО | t
(1 row)
This only happens on our production database - which has the following encoding settings
Name | Owner | Encoding | Collate | Ctype |
----------------+----------------+----------+-------------+-------------+
PROD DB | PROD DB OWNER | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
This is pretty baffling to me so an ideas about what to check next would be helpful
EXPLAIN (ANALYZE, BUFFERS)
is almost always helpful to include with such questions (or at leastEXPLAIN
if the executed query fails).