2010-02-03 112 views
1

我們有一個關於mysql的表來記錄我們網站的所有訪問者。該結構如下所示MySQL查詢問題 - 計數查詢使用大量的CPU

 
    CREATE TABLE `tblvisitors` (
     `visitorURL` longtext, 
     `visitorDatetime` datetime DEFAULT NULL, 
     `visitorIP` varchar(255) DEFAULT NULL, 
     `visitorID` int(10) NOT NULL AUTO_INCREMENT, 
     `visitorUser` varchar(255) DEFAULT NULL, 
     `visitorShow` varchar(50) DEFAULT NULL, 
     `visitorIPcaption` varchar(255) DEFAULT NULL, 
     `visitorIPRange` varchar(255) DEFAULT NULL, 
     PRIMARY KEY (`visitorID`), 
     KEY `INDEXDT` (`visitorDatetime`), 
     KEY `INDEXIP` (`visitorIP`) 
    ) ENGINE=MyISAM DEFAULT CHARSET=latin1; 

表有現在超過500萬分的記錄。

我們每半秒執行一次INSERT操作,每半秒執行一次SELECT操作,其中涉及visitorURL列上的CRITERIA和COUNT字段的Select。

查詢是:

 
    SELECT COUNT(visitorURL) FROM tblVisitors 
     WHERE visitorURL='http://mihirdarji.com/something' 

這將拍攝的CPU使用率90%與8 GB內存的8核心服務器。

MySQL管理器顯示很多連接上面的查詢等待執行。

任何建議將受到歡迎。

解釋計劃說

 
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | 
| 1 | SIMPLE | tblVIsitors | ALL | NULL | NULL | NULL | NULL | 4293277 | Using where | 

回答

1
  1. 先上visitorURL
  2. 創建索引僅次於COUNT一些靜態SELECT COUNT(1) FROM tblVisitors WHERE visitorURL=...
+0

-visitorURL是longtext我不確定索引是否可以工作 - 將嘗試使用靜態東西 – Mihir 2010-02-03 07:59:51

+0

您可以肯定地在長文本上添加索引:「對於BLOB和TEXT列上的索引,必須指定一個索引前綴長度」c.f.http://dev.mysql.com/doc/refman/5.0/en/blob.html – 2010-02-03 20:13:18

0

你有沒有在這個表上定義的索引?如果不是,您應該在visitorURL欄中確定make an index。您當前的查詢需要全表掃描,這需要很長時間。但是,如果使用簡單索引(因爲唯一字符串的數量與表中的記錄數量相似),索引長文本字符串可能會提高所需速度。因此,在這種情況下,全文索引可能是更好的選擇。這將要求您使用特殊的"full-text search functions"

+0

我會嘗試併發送更新,如果成功 – Mihir 2010-02-03 08:01:11

+0

全文不允許我匹配確切的URL,我可以以某種方式匹配嗎? – Mihir 2010-02-03 10:16:07

+0

所以問題是,你在這個'visitorURL'字段中存儲了什麼?它是HTTP引用者還是它是你的網站之一?我只是想,有多少不同的值可以在這一列 – naivists 2010-02-03 11:53:01

0

visitorIp是否真的需要varchar(255)?

+0

是的,它是必需的 – Mihir 2010-02-03 08:00:25

+0

啊,我現在看到。你匹配了其他列的長度。 – rrrfusco 2010-02-03 14:52:07

0

運行該query

+0

像其他人一樣,需要在visitorURL上創建索引,'possible_keys'爲'null': 如果此列爲NULL,則有沒有相關指標。在這種情況下,您可以通過檢查WHERE子句來檢查是否引用某些適合索引的列或列,從而提高查詢的性能。如果是這樣,請創建一個適當的索引,並再次使用EXPLAIN檢查查詢 – 2010-02-03 08:40:34

+1

thnx,但將在此類查詢中使用全文索引幫助 – Mihir 2010-02-03 10:15:08

1

而不是索引URL列,您可以將URL的散列值存儲在單獨的varchar列和索引中並查詢該值。但是無論你做什麼,你都需要一個你正在計算的列的索引。另請參閱MyIsam keycache設置,以確保儘可能有效地處理索引。