2011-11-01 36 views
0

我想我已經優化了我所能做以下表結構:沒有更多的MySQL表優化?

CREATE TABLE `sal_forwarding` (
    `sid` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, 
    `f_shop` INT(11) NOT NULL, 
    `f_offer` INT(11) DEFAULT NULL, 
    . 
    . 
    . 
    . 
    . 
    `f_affiliateId` TINYINT(3) UNSIGNED NOT NULL, 
    `forwardDate` DATE NOT NULL, 
    PRIMARY KEY (`sid`), 
    KEY `f_partner` (`f_partner`,`forwardDate`), 
    KEY `forwardDate` (`forwardDate`,`cid`), 
    KEY `forwardDate_2` (`forwardDate`,`f_shop`), 
    KEY `forwardDate_3` (`forwardDate`,`f_shop`,`f_partner`), 
    KEY `forwardDate_4` (`forwardDate`,`f_partner`,`cid`), 
    KEY `forwardDate_5` (`forwardDate`,`f_affiliateId`), 
    KEY `forwardDate_6` (`forwardDate`,`f_shop`,`sid`), 
    KEY `forwardDate_7` (`forwardDate`,`f_shop`,`cid`), 
    KEY `forwardDate_8` (`forwardDate`,`f_affiliateId`,`cid`) 
) ENGINE=INNODB AUTO_INCREMENT=10946560 DEFAULT CHARSET=latin1 

這是EXPLAIN語句:

id select_type table   type possible_keys                         key    key_len ref  rows Extra 
1 SIMPLE  sal_forwarding range forwardDate,forwardDate_2,forwardDate_3,forwardDate_4,forwardDate_5,forwardDate_6,forwardDate_7,forwardDate_8 forwardDate_7 3  (NULL) 1221784 Using where; Using index; Using filesort 

下面的查詢需要23秒閱讀2300行:

SELECT COUNT(sid),f_shop, COUNT(DISTINCT(cid)) 
FROM sal_forwarding 
WHERE forwardDate BETWEEN "2011-01-01" AND "2011-11-01" 
GROUP BY f_shop 

我該怎麼做才能提高性能? 非常感謝。

回答

1

稍微修改你所擁有的...使用count(*)而不是實際字段。對於DISTINCT,你不需要()。它可能會讓你對所有的索引感到困惑。卸下forwardDate與以外的所有其他指數基於(forwardDate,f_shop,CID)(您當前KEY7指數)有一個

SELECT 
     COUNT(*), 
     f_shop, 
     COUNT(DISTINCT cid) 
    FROM 
     sal_forwarding 
    WHERE 
     forwardDate BETWEEN "2011-01-01" AND "2011-11-01" 
    GROUP BY 
     f_shop 

然後,咧嘴一笑,既然沒有別的似乎爲你工作,嘗試投入上記錄的預子查詢,然後從該綜上所述,所以根據您的近1100萬條記錄它不依賴於任何其它索引頁(每個自動增量值隱含的)...

SELECT 
     f_shop, 
     sum(PreQuery.Presum) totalCnt, 
     COUNT(*) dist_cid 
    FROM 
     (select f_shop, cid, count(*) presum 
      from sal_forwarding 
      WHERE forwardDate BETWEEN "2011-01-01" AND "2011-11-01" 
      group by f_shop, cid) PreQuery 
    GROUP BY 
     f_shop 

由於內部預查詢是通過F_Shop和C_ID(通過索引進行優化)進行記錄和分組的簡單計數,現在您將擁有獨特的已經彙總的vi一個簡單的計數...然後做內部計數的「presum」列的SUM()。再次,嘗試和轉換表格的另一種選擇,希望它適用於你。

+0

你好,查詢更新不會提高性能,其他查詢正在被其他查詢使用,這就是爲什麼我需要這麼多索引。 – user954740

+0

@ user954740,增加了額外的查詢選項供您試用。 – DRapp

+0

你好,感謝您的幫助,但其他查詢看起來非常複雜,需要一分鐘以上。 ;-) – user954740

0

我不認爲(forwardDate, f_shop, cid)適合此查詢。由於forwardDate列中的範圍條件,不比簡單的(forwardDate)索引更好。

您可以嘗試(f_shop, cid, forwardDate)索引。

+0

你好,這是我的大問題。我從來沒有準備好任何有關正確使用索引的好文檔。我不知道哪個訂單是最好的,爲什麼。我會嘗試你的提示。 – user954740

+0

問題是'(forwardDate,f_shop,cid)'是這個查詢的最佳索引,但由於索引第一部分的範圍條件,MySQL無法使用它。如果你有'forwardDate ='2011-01-01'',而不是'BETWEEN ...',它會被使用。 –

+0

查詢不使用剛剛存在的新索引,它告訴我它是更好的索引。 – user954740