2015-10-05 37 views
1

我有這樣的聊天表:指數聊天MySQL表

CREATE TABLE IF NOT EXISTS `support_chat` (
     `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, 
     `from` varchar(255) NOT NULL DEFAULT '', 
     `to` varchar(255) NOT NULL DEFAULT '', 
     `message` text NOT NULL, 
     `sent` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', 
     `seen` varchar(1) NOT NULL DEFAULT '0', 
     PRIMARY KEY (`id`), 
     KEY `from` (`from`), 
     KEY `to` (`to`) 
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=1 ; 

基本上我需要做一個選擇所有的時間(每個用戶3秒),以檢查新郵件:

select id, `from`, message, sent from support_chat where `to` = ? and seen = 0 

我有5個百萬行,通常同時在線100個用戶。我能改變一些東西來使這張桌子更快嗎?關鍵和關鍵是一個很好的選擇?

+0

看來你有2個賬戶。請閱讀如何合併它們:[我意外創建了兩個帳戶;我如何合併它們?](http://dba.stackexchange.com/help/merging-accounts) –

回答

1

您可以通過索引來加速該特定查詢。你可以在to和seen字段上有一個複合索引,但是如果有的話,改進將是最小的。爲什麼?因爲看到的領域有很差的基數。你似乎只在其中存儲0或1,並且在這樣的列上的索引不是非常有用的。查詢優化器通常會更快地直接讀取數據。

但在這裏你可以做什麼Partition

...使您可以根據其需要,你可以在很大程度上設置的規則跨越 文件系統分配單個表的部分。在 效應中,表格的不同部分作爲不同位置的單獨表格存儲。用戶選擇的規則由 數據的劃分完成被稱爲分區函數,

您可以在很老的數據是從分離的新的方式劃分您的數據。這可能會給你一個很大的提升。但是請注意,如果您有一個查詢可以提取舊數據以及會慢很多的新數據。

以下是您可以做的另一件事:添加限制條款。 您可能在任何給定時間只顯示有限數量的消息。設置限制條款將有所幫助。然後,mysql知道在找到N行後它不需要再看。

+1

非常感謝!我會檢查這個分區提示併爲我的查詢設置限制! –

+0

'看到'具有較差的基數,但'''有很好的。使用索引可以顯着提高效率。 –

1

在此特定順序上添加多列索引,並在該列中添加看到的列(列應該是索引中的第一列)。然後在您的查詢上運行explain select ...以查看是否使用了新索引。

+1

是這樣的? KEY('to','seen') - 我應該把鑰匙從鑰匙上還是鑰匙上? –

0

假設只有seen列中存儲2個值('0''1'),並且to列存儲聊天消息(電子郵件,用戶名)的接收者,所以它可以有許多更多的值,我會使用一個綜合指數與seen第一和第二to

ALTER TABLE support_chat 
    ADD INDEX seen_to_ix 
    (seen, `to`) ; 

以相反的順序(`to`, seen)的複合指數將是一個不錯的選擇,太多。根據服務器負載和更新表的頻率,它甚至可能會更好。一個優點(如果您決定使用第二個索引),您可以刪除(`to`)索引。
選取並添加兩個索引之一,然後再次檢查查詢的性能。

其他注意事項:

  • 使用varchar(1)什麼本質上是一個布爾值不是最優的。更糟的是,它是一個utf8mb4字符集。它使用5個字節!(1爲變量,4爲單字節!)
    我會將該列的類型更改爲tinyint(和存儲01)或bit

  • 請避免對錶名和列名使用保留字(例如,from,to)。