Bedre performance på enormt mange mange-til-mange
Jeg har 3 tabeller som er forbundet med en mange-til-mange relation:- Posts
- Categories
- Categorizations
Categorizations er en mange-til-mange tabel mellem Posts og Categories. Min opgave er at finde Posts som er medlem af nogle bestemte Categories. Jeg har fået hjælp af bl.a. arne_v (tak) til at gøre det sådan:
SELECT COUNT(DISTINCT p1.id) AS count
FROM posts p1
INNER JOIN categorizations pc1 ON p1.id = pc1.postid
INNER JOIN categories c1 ON pc1.categoryid = c1.id
INNER JOIN posts p2 ON p1.id = p2.id
INNER JOIN categorizations pc2 ON p2.id = pc2.postid
INNER JOIN categories c2 ON pc2.categoryid = c2.id
WHERE (pc1.categoryid = 735) AND (pc2.categoryid = 1187)
Det fungerer rigtig fint, men problemet opstår når jeg prøver med flere end to kategorier. F.eks. 5, hvilket ser sådan ud:
SELECT distinct p1.Id, p1.Title, p1.Text, p1.UserId, p1.VoteCount,
p1.ContentType, p1.IsHardcore, p1.SourceUrl, p1.Alias, p1.CommentCount,
p1.SubmittedTime, p1.RecentVoteCount, p1.PrimaryImageUrl
FROM Posts p1
INNER JOIN categorizations pc1 ON p1.Id = pc1.PostId
INNER JOIN posts p2 ON p1.id = p2.id
INNER JOIN categorizations pc2 ON p2.Id = pc2.PostId
INNER JOIN posts p3 ON p2.id = p3.id
INNER JOIN categorizations pc3 ON p3.Id = pc3.PostId
INNER JOIN posts p4 ON p3.id = p4.id
INNER JOIN categorizations pc4 ON p4.Id = pc4.PostId
INNER JOIN posts p5 ON p4.id = p5.id
INNER JOIN categorizations pc5 ON p5.Id = pc5.PostId
WHERE ( (pc1.CategoryId = 1256)
OR (pc2.CategoryId = 770)
OR (pc3.CategoryId = 677)
OR (pc4.CategoryId = 1262)
OR (pc5.CategoryId = 937) )
ORDER BY p1.SubmittedTime DESC
Det kald tager 20 sekunder, selvom der ikke er mange data - og det lader til at tage eksponentielt længere tid for hver ekstra kategori som tilføjes. Hvis jeg bruger AND i stedet for OR, svarer den næsten med det samme.
Nogle forslag til hvordan jeg kan opnå rimelig ydelse for et kald hvor jeg vil hente alle Posts som er medlem af én eller flere kategorier?