Steven Grimm schrieb am 14.11.2015 um 07:25:
We have a table, call it "multi_id", that contains columns with IDs of various
kinds of objects in my system,
and another table that's a generic owner/key/value store for object attributes
(think configuration settings,
and I'll refer to this table as "settings"). To wit:
---------------------------------------------
CREATE TABLE multi_id (
id1 INTEGER PRIMARY KEY,
id2 INTEGER,
id3 INTEGER
);
CREATE TABLE settings (
owner_id INTEGER,
setting_id INTEGER,
setting_value TEXT,
PRIMARY KEY (owner_id, setting_id)
);
CREATE UNIQUE INDEX multi_id_idx_id1 ON multi_id (id1, id2);
CREATE UNIQUE INDEX multi_id_idx_id2 ON multi_id (id2, id1);
CREATE INDEX settings_idx_setting_id ON settings (setting_id, setting_value);
---------------------------------------------
We want to find all the rows from multi_id where any of the IDs (including its
primary key) have a certain setting with a certain value.
LATERAL seemed like the tool for the job, so we tried the following:
---------------------------------------------
SELECT mid.id1
FROM multi_id AS mid,
LATERAL (
SELECT 1
FROM settings
WHERE setting_id = 1
AND setting_value = 'common_1'
AND owner_id IN (mid.id1, mid.id2, mid.id3)
) AS setting_matcher;
---------------------------------------------
The above is actualy a CROSS JOIN between multi_id and settings which generates
duplicate values for id1 and is probably not what you want
I _think_ what you are after is something like this:
with sett as (
SELECT owner_id
FROM settings
WHERE setting_id = 1
AND setting_value = 'common_1'
)
select mid.id1
from multi_id as mid
where exists (SELECT 1
FROM sett
WHERE owner_id = mid.id1)
or exists (SELECT 1
FROM sett
where owner_id = mid.id2)
or exists (SELECT 1
FROM sett
where owner_id = mid.id3);
This returns the same result as your original query (when I apply a DISTINCT on
it to remove the duplicate ids).
It runs in 23ms on my computer, your cross join takes roughly 4 seconds.
This is the plan from your statement: http://explain.depesz.com/s/EyjJ
This is the plan for my statement: http://explain.depesz.com/s/Dt7x
--
Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general