0

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
8
  • I would start by adding an index on table_b.foo. Feb 12, 2022 at 9:25
  • 2
    I doubt it will make any performance difference but you can simplify the join conditions to: ta.col1 is not distinct from tb.col1 which will automatically take care of the NULL values
    – user1822
    Feb 12, 2022 at 9:27
  • Would a compound key be an option? Feb 12, 2022 at 12:33
  • 1
    What's keeping you from trying? Feb 12, 2022 at 12:45
  • 1
    Please provide information as instructed here: dba.stackexchange.com/tags/postgresql-performance/info Most importantly: explain your NULL values. Why NULL to begin with? Why join on NULL? How many are there? How many matches? General cardinalities? Why no WHERE clause? Do you always need the complete table? How much write activity? Feb 12, 2022 at 14:32

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.