Search code examples
sqlpostgresqljoindatabase-designpostgresql-performance

Inner join performance


I have a table that has a lot of foreign keys that I will need to inner join so I can search. There might be upwards of 10 of them, meaning I'd have to do 10 inner joins. Each of the tables being joined may only be a few rows, compared to the massive (millions of rows) table that I am joining them with.

I just need to know if the joins are a fast way (using only Postgres) to do this, or if there might be a more clever way I can do it using subqueries or something.

Here is some made up data as an example:

create table a (
   a_id serial primary key,
   name character varying(32)
);
create table b (
   b_id serial primary key,
   name character varying(32)
);

--just 2 tables for simplicity, but i really need like 10 or more

create table big_table (
   big_id serial primary key,
   a_id int references a(a_id),
   b_id int references b(b_id)
);

--filter big_table based on the name column of a and b
--big_table only contains fks to a and b, so in this example im using
--left joins so i can compare by the name column
select big_id,a.name,b.name from big_table
  left join a using (a_id)
  left join b using (b_id)
  where (? is null or a.name=?) and (? is null or b.name=?);

Solution

  • Basically, joins are a fast way. Which way might be the fastest depends on the exact requirements. A couple of hints:

    • The purpose of your WHERE clause is unclear. It seems you intend to join to all look-up tables and include a condition for each, while you only actually need some of them. That's inefficient. Rather use and only include in the query what you actually need.

    • With the current query, since all of your fk columns in the main table can be NULL, you must use LEFT JOIN instead of JOIN or you will exclude rows with NULL values in the fk columns.

    • The name columns in the look-up tables should certainly be defined NOT NULL. And I would not use the non-descriptive column name "name", that's an unhelpful naming convention. I also would use text instead of varchar(32).