我正在尝试提高查询的性能。据我了解,当我认为没有必要时EXPLAIN ANALYZE
,我的查询考虑了太多记录。songs
共有三个表artists(artist_id, score)
和。songs(song_id, artist_id)
listened(song_id)
我当前的查询如下所示:
WITH artists_ranked AS (
SELECT
artist_id
, rank() OVER (ORDER BY score ) rnk
ORDER BY rnk ASC
),
not_listened_songs AS (
SELECT *
FROM songs
WHERE NOT EXISTS(
SELECT 1
FROM listened
WHERE listened.song_id = songs.song_id) -- bad: I go through all songs
),
shuffled_songs AS (
SELECT *
FROM artists_ranked
JOIN not_listened_songs ON not_listened_songs.artist_id = artists_ranked.artist_id
ORDER BY random() --bad: I shuffle all songs
)
SELECT DISTINCT ON (artist_id) *
FROM shuffled_songs
LIMIT 1;
理想情况下(至少在我看来),查询应遵循以下步骤:
- 按等级对
artists
表格进行排名。 拿一批评分最高的艺术家。可以是一位或多位艺术家。
加入表格
songs
,但排除已listened
歌曲。现在我们想随机选择一首歌曲,给每个艺术家平等的机会。
ORDER BY random()
,DISTINCT BY (artist_id)
,LIMIT 1
如果有这样的歌曲,我们停止并返回它。否则,取下一批艺术家(排名最接近的较低等级)并重复这些步骤。
- 要停止,要么返回一首歌曲(很可能在几次迭代之后),要么已经考虑了所有艺术家。
谢谢你。