2012-07-31 87 views
0

任何人都可以幫助我優化此查詢。它需要一些時間來運行:使用filesort和臨時優化查詢

的su_pref表有近90萬行

SELECT p.mykey, 
     p.merchant_name, 
     m.merchant_url, 
     p.name, 
     p.description, 
     p.image_url, 
     p.deep_link, 
     p.rrp_price, 
     p.display_price, 
     c.category, 
     p.su_parent_name 
FROM su_pref p # 
     INNER JOIN su_categoryrefs cr ON p.mykey = cr.mykey 
     INNER JOIN su_categories c ON cr.id = c.id 
     INNER JOIN su_merchants m ON p.merchant_id=m.id 
WHERE 
    cr.id =36 
ORDER BY p.date_created DESC LIMIT 0,20 

這是我所得到的,當我使用EXPLAIN

enter image description here 我真的很努力理解如何使用EXPLAIN優化查詢,所以任何幫助將不勝感激。

以下是表格定義。該su_pref表是相當大的,所以我剝奪某些領域出

CREATE TABLE `su_pref` (
    `mykey` varchar(50) NOT NULL, 
    `merchant_id` smallint(3) default NULL, 
    `merchant_name` varchar(50) NOT NULL default '', 
    `brand` varchar(50) default NULL, 
    `merchantproductkey` varchar(50) default NULL, 
    `upc` varchar(15) default NULL, 
    `name` varchar(255) NOT NULL default '', 
    `description` varchar(2500) NOT NULL default '', 
    `short_description` varchar(500) default NULL, 
    `thumb_url` varchar(500) default NULL, 
    `image_url` varchar(500) default NULL, 
    `deep_link` varchar(1000) default NULL, 
    `merchant_link` varchar(255) default NULL, 
    `rrp_price` decimal(11,2) default NULL, 
    `display_price` decimal(11,2) default NULL, 
    `delivery_cost` decimal(11,2) default NULL, 
    `price_range` tinyint(1) default NULL, 
    `keywords` varchar(500) default NULL, 
    `su_parent_name` enum('Women','Men','') NOT NULL, 
    `date_created` date default NULL, 
    `date_modified` datetime default NULL, 
    `wp_featured` varchar(1) default NULL, 
    `hp_featured` varchar(1) default NULL, 
    `published` varchar(1) default NULL, 
    `in_todays_feed` varchar(1) default NULL, 
    PRIMARY KEY (`mykey`), 
    KEY `merchant_id` (`merchant_id`), 
    KEY `date_created` (`date_created`), 
    FULLTEXT KEY `product_search` 
       (`name`,`description`,`short_description`, 
       `keywords`, `product_type`,`colour`,`style`, 
       `material`,`datafeed_category_name`, 
       `datafeed_subcategory_name`, 
       `brand`,`merchant_name`), 
    FULLTEXT KEY `name` (`name`,`datafeed_category_name`, 
         `datafeed_subcategory_name`,`product_type`,`keywords`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 

-

CREATE TABLE `su_categories` (
    `id` mediumint(9) NOT NULL, 
    `category` varchar(100) NOT NULL, 
    `parent_id` tinyint(4) NOT NULL, 
    `update_query` varchar(3000) default NULL, 
    `url` varchar(150) default NULL, 
    `last_update` datetime default NULL, 
    PRIMARY KEY (`id`,`category`,`parent_id`), 
    KEY `parent_id` (`parent_id`), 
    KEY `category_id` (`id`), 
    FULLTEXT KEY `category_name` (`category`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 

-

CREATE TABLE `su_categoryrefs` (
    `mykey` varchar(255) NOT NULL, 
    `id` smallint(4) NOT NULL, 
    PRIMARY KEY (`mykey`,`id`), 
    KEY `id` (`id`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 

-

CREATE TABLE `su_merchants` (
    `id` mediumint(9) NOT NULL, 
    `merchant_name` varchar(40) NOT NULL, 
    `merchant_url` varchar(40) default NULL, 
    `merchant_website` varchar(40) default NULL, 
    `merchant_description` varchar(2000) default NULL, 
    `merchant_featured` varchar(1) default NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `merchant_name` (`merchant_name`) 
) ENGINE=MyISAM AUTO_INCREMENT=128 DEFAULT CHARSET=latin1 

預先感謝您

+0

我看不到屏幕截圖,但是您是否在某些字段上有索引? – JonH 2012-07-31 18:47:35

+0

嗨,是的,我有我加入和date_created所有領域的索引 – Amara 2012-07-31 18:58:54

+0

聯接中的兩列:「ON cr.id = c.id'是不同的數據類型(一個是」SMALLINT「,另一個是'MEDIUMINT')。這並不好, – 2012-07-31 21:37:56

回答

2

無法判斷哪些表中的每個不合格列都正在返回,或JOIN謂詞中的「merchant_id」正在從哪個表中引用,或者引用了ORDER BY子句中的哪個表date_created。 (我們可以做出一些猜測,但他們只是說,猜測。

第一步,真的,是限定所有這些列引用與任一表名,或者最好是表的別名。

此外,格式化的語句,使凡人可以理解它幫了不少忙。

你有合格列引用格式化聲明幫助和模式定義的包容也有幫助。(我會得到我的回答更新)

SELECT p.mykey 
    , p.merchant_name 
    , merchant_url 
    , `name` 
    , description 
    , image_url 
    , deep_link 
    , rrp_price 
    , display_price 
    , category 
    , su_parent_name 
FROM su_pref p 
JOIN su_categoryrefs cr ON cr.mykey = p.mykey 
JOIN su_categories c ON c.id  = cr.id 
JOIN su_merchants m  ON m.id  = p.merchant_id 
WHERE cr.id = 36 
ORDER BY date_created DESC LIMIT 0,20 

作爲一般的經驗法則,希望在連接謂詞中引用具有前導列的索引。通常,這些是PRIMARY KEY和所有外鍵。此外,如果是「覆蓋索引」(包含查詢中引用的所有列的索引),則會在EXPLAIN輸出中看到「使用索引」;這意味着查詢在索引中得到滿足,而無需引用數據塊。

EXPLAIN似乎顯示被引用的「colour_id」索引,但它並不明顯指出哪個列包含在該索引中。 (EXPLAIN PLAN輸出圖像太難閱讀了。)


這裏有一些建議:

確保你有一個指標

ON su_categories (id, category)  -- you do 
ON su_merchants (id, merchant_url) -- never mind this one, it's a small table 
ON su_categoryrefs (id, mykey) 

我假設在su_categoryrefs表中的列id是一個外鍵引用su_categories.id,而不是表的主鍵。 (這看起來像是一個關係表,它可以解決su_categories和'su_preferences`之間的多對多關係,但我只是猜測。

+0

嗨,感謝您的回答,我儘可能地更新了我的問題,謝謝您的建議。 colour_id引用不正確,我複製了另一個表並忘記重命名索引,我更新了該圖像並更改了圖像,但不幸的是,我似乎無法將圖像放大。關於索引,它們都是單獨的索引,除了cr表中的mykey索引外,它還包含一個外鍵也 – Amara 2012-07-31 20:11:16

+0

我想如果沒有看到全表定義 – Amara 2012-07-31 20:15:37

+0

@Amara,從EXPLAIN輸出的純文本(從mysql命令行客戶端獲得)將很好地工作。 – spencer7593 2012-07-31 20:31:04

相關問題