1. 程式人生 > >mysql select中子查詢中使用強制索引的優化案例

mysql select中子查詢中使用強制索引的優化案例

1,朋友找我幫忙看下比較慢的sql語句

SELECT
    pg.product_goods_id,
    pg.product_id,
    pg.pdt_code,
    pg.pdt_name,
    pg.brand_name,
    pg.reference_price,
    pg.deposit,
    pg.sale_status,
    pg.is_delete,
    pg.create_date,
    pg.create_operator,
    pg.update_date,
    pg.update_operator,
    si.shop_id,
    si.shop_name,
    pg.goods_img_url,
    pg.is_bargain,
    pg.qr_code_url,
    (
        SELECT
            COUNT(*)
        FROM
            product_attention pa
        WHERE
            pa.product_goods_id = pg.product_goods_id
        AND `status` = 0
    ) AS laud,
    pc.category_name,
    pg.is_experience,
    pg.deposit,
    pg.buy_type,
    pg.content,
    pg.assure_flag,
    pg.market_price,
    pg.qty_cnt,
    pg.sales_cnt
FROM
    product_goods pg 
LEFT JOIN shop_info si ON si.shop_id = pg.shop_id
LEFT JOIN product_category pc ON pc.category_id = pg.category_id
WHERE
    si.market_id IN (1, 2, 3, 12, 13) 
 ORDER BY pg.update_date DESC , pg.product_goods_id DESC
LIMIT 0,
 20;

問題1,加上如下的子查詢,比較慢

        (
                SELECT
                    COUNT(*)
                FROM
                    product_attention pa
                WHERE 
                    pa.product_goods_id = pg.product_goods_id
                AND `status` = 0
            ) AS laud,

這裡加上去就有點慢,有什麼優化辦法麼,詢問有啥方法?

2,我讓他提供了explain分析下執行結果

C:\Users\Administrator\Pictures\1105\e1.jpg
這裡寫圖片描述
從中可以看到,pg表中用到了臨時表空間也用到了filesort,這個點比較麻煩了。

3,我讓他提供下涉及到的幾個表的索引情況

、pa.jpg
這裡寫圖片描述
、si.jpg
這裡寫圖片描述
、pg.jpg
這裡寫圖片描述

幾個表的資料量都不大,product_goods 6w多條,其他3千多條。不應該這麼慢的。

4,去掉order by後比較快的思考

我猜猜可能是order by引起的,我讓去掉order by之後,他說比較快,但是這個order by不能輕易去掉,因為這是也許需要。但是order by欄位裡面有 product_goods_id。

5,解決方案:強制使用主鍵索引

分析到引起蠻的order by以及子查詢裡面都有product_goods_id欄位,而且這個欄位是pg表的主鍵,這麼可以強制使用主鍵索引而不走shop_id的索引,我讓他採用product_goods pg force index(PRI) 強制使用主鍵索引,我這樣想,主要是因為這個語句的子查詢用的是主鍵關聯,但是explain的時候用的是shop_id的索引,我就懷疑是走了這個shop_id的索引導致的。如果不走這個shop_id欄位的索引,直接走主鍵id既然兼顧到了join錶鏈接又兼顧到了子查詢了。

結果,他測試了後,發現快了許多,問題解決,expain結果如下ok.jpg所示,已經沒有using temporary這一項了。
這裡寫圖片描述