[英]composite index on large table, optimizing aggregate query
我們在MySql 5.5中有一個大表(擁有1.6億條記錄)。
我們安裝了mysql的機器有4GB RAM
表模式
+---------------+---------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------+---------------+------+-----+---------+-------+
| domain | varchar(50) | YES | MUL | NULL | |
| uid | varchar(100) | YES | | NULL | |
| sid | varchar(100) | YES | MUL | NULL | |
| vurl | varchar(2500) | YES | | NULL | |
| ip | varchar(20) | YES | | NULL | |
| ref | varchar(2500) | YES | | NULL | |
| stats_time | datetime | YES | MUL | NULL | |
| country | varchar(50) | YES | | NULL | |
| region | varchar(50) | YES | | NULL | |
| place | varchar(50) | YES | | NULL | |
| email | varchar(100) | YES | MUL | NULL | |
+---------------+---------------+------+-----+---------+-------+
索引
+------------+------------+------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+------------+------------+------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| visit_views | 1 | sid_index | 1 | sid | A | 157531031 | NULL | NULL | YES | BTREE | | |
| visit_views | 1 | domain_index | 1 | domain | A | 17 | NULL | NULL | YES | BTREE | | |
| visit_views | 1 | email_index | 1 | email | A | 392845 | NULL | NULL | YES | BTREE | | |
| visit_views | 1 | stats_time_index | 1 | stats_time | A | 78765515 | NULL | NULL | YES | BTREE | | |
+------------+------------+------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
示例查詢
SELECT count(*)
FROM visit_views
WHERE domain ='our'
AND email!=''
AND stats_time BETWEEN '2010-06-21 00:00:00' AND '2015-08-21 00:00:00';
我們在上面的查詢上的性能非常慢,所以我想在這個表上添加復合索引
我跑了以下命令
ALTER TABLE visit_views ADD INDEX domain_statstime_email (domain,stats_time,email);
運行此命令后,我們的表被鎖定,它已達到連接限制(連接限制為1000)。 現在表沒有響應任何INSERTS和SELECTS。
這是我的幾個問題
1.為什么表被鎖定以及為什么表沒有釋放現有連接
2.完成索引需要多長時間。 我申請3小時仍然沒有創建索引。
3.如何看待索引創建進度。
4.為表添加索引時,為什么連接限制突然增加到最大值。
5.為這種大型表添加復合索引是安全的
6.如果我為此表添加分區,它會有更好的性能。
我對索引知之甚少
一些統計數據
+---------------------------+
| @@innodb_buffer_pool_size |
+---------------------------+
| 3221225472 |
+---------------------------+
您的查詢有三個條件:不等式,等式和范圍。
WHERE domain ='our'
AND email!=''
AND stats_time BETWEEN '2010-06-21 00:00:00' AND '2015-08-21 00:00:00';
要使其工作,您應該嘗試以下索引以查看哪個更好。
(email, domain, stats_time)
(domain, email, stats_time)
為什么這些? MySQL索引是BTREE。 也就是說,它們按順序排序。 因此,為了滿足查詢,MySQL找到索引中與查詢匹配的第一個元素。 這是基於域名,電子郵件和起始stats_time值。 然后,它按順序掃描索引,查找最后一個匹配值。 一路上它會對記錄進行計數,並且滿足您的查詢。 換句話說,它在stats_time上進行范圍掃描。
為什么選擇? 我不知道MySQL會對你的電子郵件匹配謂詞中的不等性做些什么。 這就是我建議嘗試兩者的原因。
如果您還沒有簡化您向我們展示的查詢 ,您也可以嘗試覆蓋索引的復合詞
(domain, stats_time, email)
這將立即隨機訪問第一個匹配的域/ stats_time組合,然后掃描到最后一個。 在掃描時,它將查看索引中的電子郵件值(這就是為什么將其稱為覆蓋索引)並選擇匹配的行。 一路上它計算行數。
您應該考慮將您的email
列聲明為NOT NULL
以幫助您的不等式測試更有效地使用其索引。 請閱讀http://use-the-index-luke.com/以獲取更多背景信息。
至於你的問題:
為什么表被鎖定以及為什么表沒有釋放現有連接為什么在向表添加索引時連接限制突然增加到最大值。
將索引添加到大型表可能需要很長時間。 你的160美元,很大。 當我們繼續進行索引操作時,表的其他用戶必須等待。 因此,如果您從Web應用程序訪問此連接,則連接會等待它變為可用。
完成索引需要多長時間。 我申請3小時仍然沒有創建索引。
在安靜的系統上它會快得多。 您也可以刪除一些冗余的單列索引。 您可能希望復制表並索引副本,然后在准備好后重命名。
如何查看索引創建進度。
SHOW FULL PROCESSLIST
將顯示MySQL服務器中的所有操作。 您需要一個命令行界面來提供此命令。
為這種大型表添加復合索引是否安全
是的,當然,但生產系統需要時間。
如果我為此表添加分區,它會有更好的性能。
可能不是。 如果你不需要它們,那么刪除舊的行會有什么幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.