Consider the following situation, where the two tables below need to be joined. The query is currently performing very badly. There are no indices defined nor are the ids marked as PK.
I was thinking of a primary composite key (id, foo, col1-col6). However, that didn't work as col1-col6 can be NULL.
Then I was trying to add a relation, in that table_b
has an FK pointing to table_a.id
. However, I can't set the relation in the application logic.
How can I optimize the left join from below?
Table A
CREATE TABLE table_a
(
id uuid not null,
foo bigint not null,
col1 text,
col2 text,
col3 text,
col4 text,
col5 text,
col6 text,
-- some other columns
)
Table B
CREATE TABLE table_b
(
id uuid not null,
foo bigint not null,
col1 text,
col2 text,
col3 text,
col4 text,
col5 text,
col6 text,
-- some other columns
)
Left join
select tA.*, tB.*
from table_a as tA
left join table_b as tB
on tA.foo = tB.foo and
((tA.col1 is null and tB.col1 is null) or tA.col1 = tB.col1) and
((tA.col2 is null and tB.col2 is null) or tA.col2 = tB.col2) and
((tA.col3 is null and tB.col3 is null) or tA.col3 = tB.col3) and
((tA.col4 is null and tB.col4 is null) or tA.col4 = tB.col4) and
((tA.col5 is null and tB.col5 is null) or tA.col5 = tB.col5) and
((tA.col6 is null and tB.col6 is null) or tA.col6 = tB.col6) and
where tA.colX = 'baz`
Answers to questions from comments
Why NULL to begin with? Why join on NULL?
- I inherited the model and query/view, so can't answer taht
General cardinalities?
table_a (1) <-> table_b (0..1)
One-to-one (optional on one side)
Why no WHERE clause? Do you always need the complete table?
- Yes, mostly. Added where clause to example
How much write activity?
- Very little, mostly read as tables are part of a reporting db
Further information
PostgreSQL 11.12, compiled by Visual C++ build 1800, 64-bit
ta.col1 is not distinct from tb.col1
which will automatically take care of the NULL valuesWHERE
clause? Do you always need the complete table? How much write activity?