[英]How can I improve performance of a many-to-many SQL query?
我在書籍和流派之間有很多對很多的關系。 例如,“霍比特人”圖書可能具有類型“孩子”,“小說”和“幻想”。
這是模式:
CREATE TABLE "genre" (
"id" integer NOT NULL PRIMARY KEY,
"name" varchar(50) NOT NULL
)
;
CREATE TABLE "book_genres" (
"book_id" integer NOT NULL REFERENCES "book" ("id"),
"genre_id" integer NOT NULL REFERENCES "genre" ("id"),
CONSTRAINT book_genres_pkey PRIMARY KEY (book_id, genre_id)
)
;
CREATE TABLE "book" (
"id" integer NOT NULL PRIMARY KEY,
"name" varchar(255) NOT NULL,
"price" real NOT NULL
)
;
以及索引:
CREATE INDEX "book_genres_36c249d7" ON "book_genres" ("book_id");
CREATE INDEX "book_genres_33e6008b" ON "book_genres" ("genre_id");
CREATE INDEX "book_5a5255da" ON "book" ("price");
行數:
我正在嘗試用SQL編寫查詢,以查詢按價格排序的特定類型的所有書籍,而沒有重復。
這是我這樣做的查詢:
SELECT name, price
FROM book
WHERE book.id
IN
(SELECT book_id
FROM book_genres
WHERE genre_id = 1
OR genre_id = 2)
ORDER BY price LIMIT 10
我的問題是性能。 該查詢最多可能需要2000毫秒才能執行。 如何提高性能?
我對數據庫(Postgres 9.3)具有完全控制權,因此可以添加視圖,索引或非規范化。 我也使用Django,因此可以使用Python / Django執行多個查詢以在內存中執行操作。
SELECT b.name, b.price
FROM book b
WHERE EXISTS (
SELECT *
FROM book_genres bg
WHERE bg.book_id = b.id
AND bg.genre_id IN( 1 , 2)
)
ORDER BY b.price
LIMIT 10
;
price + LIMIT的訂單可能會導致性能下降:檢查查詢計划。
加上:用“反向”索引替換單列索引:將book_id設為FK進入books.id,並且(也許)省略代理鍵ID
CREATE TABLE book_genres
( book_id integer NOT NULL REFERENCES book (id)
, genre_id integer NOT NULL REFERENCES genre (id)
, PRIMARY KEY (book_id, genre_id)
) ;
CREATE INDEX ON book_genres (genre_id,book_id);
在大多數情況下,您可以使用JOIN
而不是子查詢來提高性能(盡管它取決於許多因素,所以):
SELECT *
FROM
(
SELECT b.name, b.price
FROM book b JOIN book_genres g ON b.book.id = g.book_id
AND g.genre_id = 1
UNION
SELECT b.name, b.price
FROM book b JOIN book_genres g ON b.book.id = g.book_id
AND g.genre_id = 2
)
ORDER BY price LIMIT 10
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.