2015-02-09 66 views
0

我見過很多像我這樣的問題,但是在閱讀完所有問題之後,我感到很困惑。提高MySQL查詢性能 - 可能的索引問題

總結 - 我有一個查詢從表中選擇產品,並從其他表中添加更多關於它們的信息。

查詢:

SELECT 
     p.product_id, 
     p.product_name, 
     p.product_seo_url, 
     p.product_second_name, 
     p.product_intro_plain, 
     p.product_price, 
     p.product_price_promo, 
     p.product_promo_expire_date, 
     p.product_views, 
     p.product_code, 
     p.product_exquisite, 
     p.product_rating, 
     p.product_votes, 
     p.product_date_added, 
     p.product_returned, 
     p.product_price_returned, 
     (SELECT gal.image_filelocation 
      FROM 3w_products_gallery gal 
      WHERE gal.product_id = p.product_id 
      ORDER BY show_order ASC 
      LIMIT 1) image_filelocation, 
     m.man_image_location, 
     m.man_name, 
     m.man_seo_url 
    FROM 
     3w_products p 
     LEFT JOIN 3w_manufacturers m 
      ON p.man_id = m.man_id 
     LEFT JOIN 3w_products_cat_rel pcr 
      ON p.product_id = pcr.product_id 
    WHERE 
      pcr.ctg_id = '19' 
     AND p.man_id = '190' 
    ORDER BY 
     p.product_id DESC 
    LIMIT 
     0, 24 

碰巧是查詢有時執行的0.001秒的奇怪的事情。有時候持續30多秒。

有什麼EXPLAIN顯示: http://i.stack.imgur.com/ZNtBX.png

我認爲問題出在表的索引。你能告訴我如何設置它們嗎?

讓我知道你是否需要任何有關表或任何其他信息!

最佳, 貝爾巴托夫

+0

你知道 「WHERE(pcr.ctg_id = '19')」,使得PCR外加入以執行內部連接? (如果您確實需要左連接,請將條件移至左連接的ON子句。) – jarlh 2015-02-09 10:50:56

+0

您錯過了'ASC LIMIT 1'附近的逗號 image_filelocation,'括號內的查詢結束後,您應該有一個逗號 – Gunaseelan 2015-02-09 10:51:39

+0

這兩者之間應該有「as」。 – 2015-02-09 10:59:49

回答

0

如果你的「ID」列實際上是數字,刪除它們周圍的引號意味着弦...即使它會以一個隱含的轉換。如果是數字,則保留數字。

正如其他人在評論中指出的那樣,您通過「pcr」別名與其條件在WHERE子句中的左連接將其轉換爲內連接。

FROM 
     3w_products p 
     LEFT JOIN 3w_manufacturers m 
      ON p.man_id = m.man_id 
     LEFT JOIN 3w_products_cat_rel pcr 
      ON p.product_id = pcr.product_id 
      AND pcr.ctg_id = 19 
    WHERE 
     AND p.man_id = 190 

由於每個字段(圖像位置)的選擇對每個記錄都進行一次,所以字段級別的查詢會導致性能下降。爲了至少有助於提高性能,表3w_products_gallery應該有一個索引ON(product_id,show_order)

您的主要3w_products表應該有一個索引(man_id,product_id)... Man_ID用於根據製造商優化WHERE子句,還包含產品ID以幫助優化ORDER BY條件。

您的3w_manufacturers表,我懷疑已經有一個有效的索引(man_id),因爲它似乎是表的主鍵。

此外,作爲基於網絡的內容,您可能會更好地通過爲「GalleryShowOrder」添加一個新列來更改DE-NORMALIZE您的產品表。然後,將一個觸發器添加到Gallery表中,以便任何插入或更新將第一個「showOrder」值推回到產品表。這樣,當您查詢時,您可以將另一個聯接添加到該產品上的該表,並按KNOWN顯示順序。如果您的圖庫正在返回1000條記錄,即使您僅限於24條記錄,仍然需要在應用訂單之前獲取所有記錄。因此,每個圖庫圖像都有1000個子查詢。

和你的領域選擇將剛剛成爲

gal.image_filelocation, 

和您的加盟將增加以下

LEFT JOIN 3w_products_gallery gal 
    on p.product_id = gal.product_id 
    AND p.GalleryShowOrder = gal.show_order 
+0

'表3w_products_gallery應該有一個索引ON(product_id,show_order)' - 好吧,它只有在給定ID有一堆圖像時纔有用。否則,普通的索引ON(product_id)'就足夠了。 – Matt 2015-02-10 07:45:41

+0

'main 3w_products表應該在(man_id,product_id)'上有一個索引' - 同樣,如果TS聲明查詢返回的行數不超過1000行,則使用組合索引優化'ORDER BY'是沒有用的。考慮一下,MySQL可能無法優化'ORDER BY DESC',因爲它需要'index ON(man_id,product_id DESC)',這是不受支持的(請參閱http://use-the-index-luke.com/sql /分揀分組/順序逐ASC-遞減-空值倒數) – Matt 2015-02-10 07:52:38