編輯:這裏是原始查詢的簡化版本如何使此查詢更有效?
SELECT p.*, shop FROM products p JOIN
users u ON p.date >= u.prior_login and u.user_id = 22 JOIN
shops s ON p.shop_id = s.shop_id
ORDER BY shop, date, product_id;
(在3.6秒開的475K行的產品表中運行),這是解釋計劃
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE u const PRIMARY,prior_login,user_id PRIMARY 4 const 1 Using temporary; Using filesort
1 SIMPLE s ALL PRIMARY NULL NULL NULL 90
1 SIMPLE p ref shop_id,date,shop_id_2,shop_id_3 shop_id 4 bitt3n_minxa.s.shop_id 5338 Using where
的瓶頸似乎是ORDER BY date,product_id
。刪除這兩個排序,查詢運行0.06秒。 (刪除兩者中的任何一個(但不是兩者)幾乎沒有影響,查詢仍然需要3秒以上)。我在產品表中的product_id和date上都有索引。我還在(產品,日期)上添加了沒有任何改進的索引。
newtover暗示問題是INNER JOIN users u1 ON products.date >= u1.prior_login
要求防止使用索引上products.date,其執行在〜0.006秒(而不是3.6秒爲原件)的查詢
兩種變化的事實已經被建議給我(而不是從這個線程)。
這一個使用子查詢,這似乎強制秩序的加入
SELECT p.*, shop
FROM
(
SELECT p.*
FROM products p
WHERE p.date >= (select prior_login FROM users where user_id = 22)
) as p
JOIN shops s
ON p.shop_id = s.shop_id
ORDER BY shop, date, product_id;
這一個使用WHERE子句做同樣的事情(儘管SQL_SMALL_RESULT的存在不會改變的執行時間,0.006秒沒有它)
SELECT SQL_SMALL_RESULT p . * , shop
FROM products p
INNER JOIN shops s ON p.shop_id = s.shop_id
WHERE p.date >= (
SELECT prior_login
FROM users
WHERE user_id =22)
ORDER BY shop, DATE, product_id;
我的理解是,這些查詢更快的工作是考慮減少其連接到商店表之前的產品表的行相關數量。我想知道這是否正確。
順便說一下,你在哪裏多的product_id行來自您需要排序的'circle_favorited'? – newtover 2011-12-22 16:53:08
@newtover用戶的多個朋友可以喜歡同樣的產品,所以每個不同的朋友,誰收藏與給定的product_id產品生成包含PRODUCT_ID(和朋友的用戶名)新行。收藏夾表中的每一行都包含一個user_id和一個二進制收藏夾值。如果此值爲0,這意味着用戶投下了產品。如果此值爲1,則用戶投票選擇產品。我根據circle_favorited進行排序,以便將投票產品的用戶與投票的用戶分開。 – jela 2011-12-22 18:28:25