簡體   English   中英

如何使此查詢更高效?

[英]how can I make this query more efficient?

編輯:這是原始查詢的簡化版本(在475K行的產品表上以3.6秒的時間運行)

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;

這是解釋計划

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表中同時具有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的存在並不會更改執行時間,沒有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;

我的理解是,由於在將產品表連接到shops表之前減少了產品表的相關行數,因此這些查詢的工作速度更快。 我想知道這是否正確。

使用EXPLAIN語句查看執行計划。 您也可以嘗試向products.dateu1.prior_login添加索引。

另外,請確保已定義外鍵並已對其進行索引。

祝好運。

我們確實需要一個解釋計划...但是

要非常小心,從表中的id中選擇* *(從another_table中選擇id)這是一個臭名昭著的事情。 通常,這些可以替換為聯接。 以下查詢可能會運行,盡管我尚未對其進行測試。

SELECT shop,
       shops.shop_id AS shop_id,
       products.product_id AS product_id,
       brand,
       title,
       price,
       image AS image,
       image_width,
       image_height,
       0 AS sex,
       products.date AS date,
       fav1.favorited AS circle_favorited,
       fav2.favorited AS session_user_favorited,
       u2.username AS circle_username
  FROM products
       LEFT JOIN favorites fav2
          ON     fav2.product_id = products.product_id
             AND fav2.user_id = 22
             AND fav2.current = 1
       INNER JOIN shops
          ON shops.shop_id = products.shop_id
       INNER JOIN users u1
          ON products.date >= u1.prior_login AND u1.user_id = 22
       LEFT JOIN favorites fav1
          ON products.product_id = fav1.product_id
       LEFT JOIN friends f1
          ON f1.star_id = fav1.user_id
       LEFT JOIN users u2
          ON fav1.user_id = u2.user_id
 WHERE f1.fan_id = 22 OR fav1.user_id = 22
ORDER BY shop,
         DATE,
         product_id,
         circle_favorited

由於排序很慢,查詢很慢這一事實非常明顯,因為在這種情況下很難找到要應用ORDER BY的索引。 主要問題是products.date >=比較,它使用ORDER BY的任何索引時都會中斷。 而且由於要輸出大量數據,MySQL開始使用臨時表進行排序。

我要做的是嘗試按已經具有所需順序的索引順序強制MySQL輸出數據,並刪除ORDER BY子句。

我不是要測試的計算機,但是我將如何做:

  • 我會做所有內部聯接
  • 然后我將LEFT JOIN到一個子查詢,該子查詢對由product_id,circle_favourited(將提供最后的排序條件)排序的收藏夾進行所有計算。

因此,問題是如何使數據在商店,日期,product_id上排序

我稍后再寫=)

UPD1:

您可能應該閱讀有關btree索引如何在MySQL中工作的內容。 mysqlperformanceblog.com上有一篇很好的文章(我目前在手機上撰寫,沒有鏈接可用)。 簡而言之,您似乎在談論單列索引,該索引基於在單列中排序的值來排列指向行的指針。 復合索引基於多個列存儲訂單。 在從索引所指向的行中檢索數據之前,大多數索引通常用於對其明確定義的范圍進行操作,以獲取大多數信息。 索引通常不知道同一張表上的其他索引,因此它們很少合並。 當索引中沒有更多信息時,MySQL開始直接對數據進行操作。

也就是說,日期索引不能使用product_id上的索引,但是日期日期后(針對特定日期匹配的產品ID排序),(日期,product_id)上的索引可以獲取有關product_id的更多信息。

但是,日期范圍條件(> =)打破了這一點。 那就是我在說的。

UPD2:

據我了解,這個問題可以減少到(大部分時間都花在此上):

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;

現在在用戶上添加索引(user_id,previous_login),在產品上添加索引(date),然后嘗試以下查詢:

SELECT STRAIGHT_JOIN p.*, shop
FROM (
  SELECT product_id, shop
  FROM users u
  JOIN products p
    user_id = 22 AND p.`date` >= prior_login
  JOIN shops s
    ON p.shop_id = s.shop_id
  ORDER BY shop, p.`date`, product_id
) as s
JOIN products p USING (product_id);

如果我是正確的,查詢應該返回相同的結果,但速度更快。 如果可以,則將EXPLAIN的結果發布給查詢。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM