2014-04-01 34 views
1

我有表:MySQL查詢優化改造子查詢DISTINCT

CREATE TABLE IF NOT EXISTS `bk_cart_rule` (
    `id_cart_rule` int(10) unsigned NOT NULL DEFAULT '0', 
    `cart_rule_restriction` tinyint(1) unsigned NOT NULL DEFAULT '0', 
    KEY `id_cart_rule` (`id_cart_rule`), 
    KEY `cart_rule_restriction` (`cart_rule_restriction`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

CREATE TABLE IF NOT EXISTS `bk_cart_rule_combination` (
    `id_cart_rule_1` int(10) unsigned NOT NULL, 
    `id_cart_rule_2` int(10) unsigned NOT NULL, 
    KEY `id_cart_rule_1` (`id_cart_rule_1`), 
    KEY `id_cart_rule_2` (`id_cart_rule_2`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 


CREATE TABLE IF NOT EXISTS `bk_cart_rule_lang` (
    `id_cart_rule` int(10) unsigned NOT NULL, 
    `id_lang` int(10) unsigned NOT NULL, 
    KEY `id_cart_rule` (`id_cart_rule`), 
    KEY `id_lang` (`id_lang`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

和查詢:

SELECT SQL_NO_CACHE cr.*, crl.*, 1 as selected FROM bk_cart_rule cr 
LEFT JOIN bk_cart_rule_lang crl ON (cr.id_cart_rule = crl.id_cart_rule AND crl.id_lang = 2) 

WHERE cr.id_cart_rule != 375 AND 
      ( cr.cart_rule_restriction = 0 OR 
       cr.id_cart_rule IN ( 
        SELECT IF(id_cart_rule_1 = 375, id_cart_rule_2, id_cart_rule_1) FROM bk_cart_rule_combination WHERE 375 = id_cart_rule_1 OR 375 = id_cart_rule_2)) 

明顯優化:

SELECT SQL_NO_CACHE DISTINCT cr.*, crl.* 1 as selected FROM bk_cart_rule cr 
LEFT JOIN bk_cart_rule_lang crl ON (cr.id_cart_rule = crl.id_cart_rule AND crl.id_lang = 2) 
LEFT JOIN bk_cart_rule_combination crc ON (375 = crc.id_cart_rule_1 AND cr.id_cart_rule = crc.id_cart_rule_2) OR (375 = crc.id_cart_rule_2 AND cr.id_cart_rule = crc.id_cart_rule_1) 
WHERE cr.id_cart_rule != 375 AND (cr.cart_rule_restriction = 0 OR NOT ISNULL(crc.id_cart_rule_1)) 

但我怎麼能擺脫DISTINCT(在bk_cart_rule_combination中我有雙向組合:)

id_cart_rule_1 id_cart_rule_2 
375 776 
776 375 

或者也許有更好的優化可能?

回答

1

如果購物車規則的排序不重要,則添加約束條件,即第一個規則的id小於第二個規則的id。也就是說,按順序把它們放在桌子上。

不幸的是,MySQL不允許簡單的check約束。相反,你必須以其他方式來實現它。這裏有三個:

  • 實施插入/更新觸發器來維護排序(並防止重複)。
  • 實現應用程序端的邏輯。
  • 將所有數據修改包裝在存儲過程中並實現存儲過程中的邏輯。

如果你不想去克服這些困難(這可能會與其他問題的幫助),你可以更換select distinct有:

group by least(id_cart_rule_1, id_cart_rule_2), greatest(id_cart_rule_1, id_cart_rule_2)