У меня есть 2 таблицы, tracklist
и track
, где tracklist
имеет много tracks
. В некоторые моменты я получу пользовательский ввод, который ссылается на список треков, и мне нужно либо создать этот треклист, либо вернуть существующий треклист (это потому, что треклисты должны быть полностью прозрачными для пользователей).
Моим наивным решением было найти все треклисты с n
треками и присоединиться к track
против tracklist
n
раз, проверяя каждое объединение по введенным пользователем данным. Например, с 2 треками:
SELECT tracklist.id FROM tracklist
JOIN track t1 ON tracklist.id = t1.tracklist
JOIN track_name tn1 ON t1.name = tn1.id
JOIN track t2 ON tracklist.id = t2.tracklist
JOIN track_name tn2 ON t2.name = tn2.id
WHERE tracklist.track_count = '20'
AND (t1.position = 1 AND tn1.name = 'Pancakes' AND t1.artist_credit = '42' AND t1.recording = 1)
AND (t2.position = 2 AND tn2.name = 'Waffles' AND t2.artist_credit = '9001' AND t2.recording = 2)
Однако, это действительно плохо масштабируется для больших треклистов. Мое очень элементарное время показывает, что это может занять> 500 мс для 10 треклистов и ~ 7 с для треклистов с 100 треками. В то время как последний является крайним случаем, любой алгоритм, который я использую, должен иметь возможность масштабироваться по крайней мере до этого.
Однако я застрял на других решениях. Единственное, о чем я могу думать, это выбрать все треклисты с дорожками n
и все их треки, а затем выполнить сравнение в коде приложения. Однако я бы очень хотел оставить это на сервере базы данных, если смогу.
Вот схема, с которой я работаю:
CREATE TABLE track
(
id SERIAL,
recording INTEGER NOT NULL, -- references recording.id
tracklist INTEGER NOT NULL, -- references tracklist.id
position INTEGER NOT NULL,
name INTEGER NOT NULL, -- references track_name.id
artist_credit INTEGER NOT NULL, -- references artist_credit.id
length INTEGER CHECK (length IS NULL OR length > 0),
edits_pending INTEGER NOT NULL DEFAULT 0,
last_updated TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
CREATE TABLE track_name (
id SERIAL,
name VARCHAR NOT NULL
);
CREATE TABLE tracklist
(
id SERIAL,
track_count INTEGER NOT NULL DEFAULT 0,
last_updated TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
Есть предложения?