2012-07-06 63 views
4

我有一個包含此結構的表,它目前包含大約160萬條記錄。如何優化包含LIKE'%abc%'查詢的160多萬條記錄的MySQL表

CREATE TABLE `chatindex` (
    `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    `roomname` varchar(90) COLLATE utf8_bin NOT NULL, 
    `username` varchar(60) COLLATE utf8_bin NOT NULL, 
    `filecount` int(10) unsigned NOT NULL, 
    `connection` int(2) unsigned NOT NULL, 
    `primaryip` int(10) unsigned NOT NULL, 
    `primaryport` int(2) unsigned NOT NULL, 
    `rank` int(1) NOT NULL, 
    `hashcode` varchar(12) COLLATE utf8_bin NOT NULL, 
    PRIMARY KEY (`timestamp`,`roomname`,`username`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; 

無論是ROOMNAME和用戶名的列包含相同的確切數據,但獨特性和每個項目的重要位來自時間戳與這兩個項目相結合。

正在啓動需要一段時間(10-20秒)查詢是這樣的:

SELECT timestamp,roomname,username,primaryip,primaryport 
    FROM `chatindex` 
    WHERE username LIKE '%partialusername%' 

我究竟能做些什麼來優化這個?我不能這樣做partialusername%,因爲對於某些查詢,我只會有一小部分實際用戶名的中心,而不是實際值開頭的前幾個字符。

編輯:

此外,將獅身人面像爲這個特殊的目的更好?

+0

如果你需要「%part%」,那麼你必須這樣做。你會用什麼查詢的結果?你可以在非數據庫方面改變你的方法嗎? – 2012-07-06 06:38:02

回答

5

使用Fulltext indexes,這些實際上是爲此目的而設計的。現在InnoDb支持MySQL 5.6.4中的全文索引。

1

在MSSQL上,這是一個與CONTAIN子句一起使用全文索引的完美案例。 LIKE子句無法在如此大的表格上獲得良好的性能,並且無法搜索許多文本變體。

看看這個鏈接,有很多與dinamic search conditions有關的問題。

4
  1. 上表中的列名(全文索引)創建索引。
  2. 作爲一個想法,您可以在此表上創建一些視圖,該視圖將基於字母或其他標準以及您的代碼將決定使用哪個視圖來獲取搜索結果的過濾數據。
2

你應該使用MyISAM表做Fulltext搜索,因爲它支持FULLTEXT索引,MySQL的V5.6 +仍處於開發階段,你不應該把它作爲一個生產服務器,它可能需要約1年走GA 。

現在,你應該此錶轉換爲MyISAM和添加是指在where子句column FULLTEXT指數:

這些鏈接可能是有用的:

http://dev.mysql.com/doc/refman/5.0/en/create-index.html

http://dev.mysql.com/doc/refman/5.1/en/fulltext-fine-tuning.html

+0

全文索引添加超過此查詢的正常索引的優點。 'username'上的任何索引都將阻止全表掃描。這種類型的查詢將不會使用全文功能。 – TerryE 2012-07-06 10:08:05

1

如果您對當前查詢做一個解釋,你會看到你正在對錶進行全表掃描,這就是爲什麼它太慢了。用戶名索引將大大提高搜索速度,因爲MySQL可以緩存索引,並且只有匹配用戶才能訪問表格條目。

一個全文索引將不會重大喜歡幫助搜索%fred%匹配oldfredboy等,所以我在虧損,爲什麼別人都在用這個建議。全文索引的作用是創建一個基於單詞表的索引,以便您可以搜索「解釋當前查詢」這樣的列表,全文引擎將包含「explain」的行ID與包含「current」的行標識符以及包含「query 「以獲得包含全部三個的ID的列表。添加一個全文索引實質上增加了插入,更新了表的刪除成本,所以它確實增加了性能損失。此外,您需要使用全文特定的「MATCH」語法來充分利用全文索引。

如果您對「[mysql]全文類似」進行問題搜索,請參閱此處的進一步討論。

一個正常的索引將做你需要的一切。像'%fred%'這樣的搜索需要對索引進行全面掃描,因此您需要儘可能保持索引儘可能精簡。另外,如果命中率高達'fred%',那麼它可能首先嚐試像'fred%'搜索,因爲這將執行索引範圍掃描。

另外一點,爲什麼您使用時間戳,房間名稱,用戶名作爲主鍵?這對我沒有意義。如果您不使用主鍵作爲訪問路徑,那麼auto_increment id更容易。我原以爲房間名稱,時間戳,用戶名會有一定的意義,因爲您肯定傾向於在一個時間窗口內訪問房間。

只添加您將使用的索引。

0

表索引(全文索引)必須適用於如此大量的數據。 如果可能,進一步去分區表。所以這些肯定會提高性能。