Mysql
Mysql Select vs Select SUM 性能
我需要檢查衝浪者是否已經投票這可以使用
方法一
Select record_num FROM table where etc etc.
IE
SELECT record_num FROM content_votes_tmp WHERE up = 1 AND ip = INET_ATON('$_SERVER[REMOTE_ADDR]') AND content = $_POST[id] AND UNIX_TIMESTAMP(datetime) > '$old_time'
方法二
Select Sum(votes) FROM table where etc etc.
IE
SELECT SUM(up) as up_count FROM content_votes_tmp WHERE ip = INET_ATON('$_SERVER[REMOTE_ADDR]') AND content = $_POST[id] AND UNIX_TIMESTAMP(datetime) > '$old_time'
使用儲存引擎作為 MyISAM ,表有大約 100 萬行,ROW 格式是靜態的。
我正在尋找性能更快的查詢。
那麼哪個查詢會更快?每次有人點擊“贊成”或“反對”按鈕時,都會觸發此查詢。,
這是一個表結構
CREATE TABLE IF NOT EXISTS `content_votes_tmp` ( `up` int(11) NOT NULL DEFAULT '0', `down` int(11) NOT NULL DEFAULT '0', `ip` int(10) unsigned NOT NULL, `content` int(11) NOT NULL, `datetime` datetime NOT NULL, `is_updated` tinyint(2) NOT NULL DEFAULT '0', `record_num` int(11) NOT NULL AUTO_INCREMENT, PRIMARY KEY (`record_num`) KEY `content` (`content`), KEY `datetime` (`datetime`), KEY `is_updated` (`is_updated`), KEY `ip` (`ip`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=25 ;
您顯示的 2 個查詢的含義不同。
第一個將在該時間範圍內選擇該 IP 和內容的所有贊成票。如果創建索引:
mysql> ALTER TABLE content_votes_tmp ADD INDEX(up, ip, content, datetime, record_num); Query OK, 753676 rows affected (3.85 sec) Records: 753676 Duplicates: 0 Warnings: 0
您可以獲得良好的性能結果 - 將使用前 2 列,您將獲得 Using Index 優化:
mysql> EXPLAIN SELECT record_num FROM content_votes_tmp WHERE up = 1 AND ip = 1 AND content = 1 AND UNIX_TIMESTAMP(datetime) > @number\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: content_votes_tmp type: ref possible_keys: up key: up key_len: 12 ref: const,const,const rows: 1 Extra: Using where; Using index 1 row in set (0.00 sec)
我們甚至可以做得更好。通過轉換 $old_time-刪除
UNIX_TIMESTAMP()
函式 -compare dates 而不是 int,並且能夠使用索引應用所有條件(3 個 consts 和 1 個範圍):mysql> EXPLAIN SELECT record_num FROM content_votes_tmp WHERE up = 1 AND ip = 1 AND content = 1 AND datetime > now()\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: content_votes_tmp type: range possible_keys: up key: up key_len: 17 ref: NULL rows: 1 Extra: Using where; Using index 1 row in set (0.00 sec)
如果應用程序的邏輯需要知道是否進行了否決,請小心,此查詢不會幫助您。
第二個需要稍微不同的索引:
mysql> ALTER TABLE content_votes_tmp ADD INDEX(ip, content, datetime, up); Query OK, 753676 rows affected (5.95 sec) Records: 753676 Duplicates: 0 Warnings: 0
為了得到一個好的查詢計劃,還需要“將函式移到操作數的另一邊”:
mysql> EXPLAIN SELECT SUM(up) as up_count FROM content_votes_tmp WHERE ip = 1 AND content = 1 AND datetime > now()\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: content_votes_tmp type: range possible_keys: ip key: ip key_len: 13 ref: NULL rows: 1 Extra: Using where; Using index 1 row in set (0.00 sec)
我不喜歡 range + SUM(),所以我更喜歡第一個,它更簡單(除非你打算返回很多行)。但是查詢計劃中沒有任何東西可以支持我的恐懼(它也有覆蓋索引優化,並且沒有文件排序,所以使用適當的索引兩者都可以非常快 - 它們使用我的假 1M 數據需要 0.00 秒)。
請記住,邏輯略有不同,因此請注意 - 如果您允許贊成和反對,這可能是一個問題。