CREATE TABLE ofRoster (
`rosterID` bigint(20) NOT NULL,
`username` varchar(64) NOT NULL,
`jid` varchar(1024) NOT NULL,
`sub` tinyint(4) NOT NULL,
`ask` tinyint(4) NOT NULL,
`recv` tinyint(4) NOT NULL,
`nick` varchar(255) DEFAULT NULL,
PRIMARY KEY (`rosterID`),
KEY `ofRoster_unameid_idx` (`username`),
KEY `ofRoster_jid_idx` (`jid`(255))
) ENGINE=InnoDB;
CREATE TABLE `ofRoster_par` (
`rosterID` bigint(20) NOT NULL AUTO_INCREMENT,
`username` int(64) NOT NULL,
`jid` varchar(1024) NOT NULL,
`sub` tinyint(4) NOT NULL,
`ask` tinyint(4) NOT NULL,
`recv` tinyint(4) NOT NULL,
`nick` varchar(255) DEFAULT NULL,
UNIQUE KEY `rosterID` (`rosterID`,`username`),
KEY `ofRoster_unameid_idx` (`username`),
KEY `ofRoster_jid_idx` (`jid`(255))
) ENGINE=InnoDB AUTO_INCREMENT=412595 DEFAULT CHARSET=latin1
/*!50100 PARTITION BY HASH (username)
PARTITIONS 10 */ ;
我在用户名上创建了分区,这样当我使用 select 命令时,它只需要在一个分区上搜索。 但我不确定这是否有益,因为用户名上已经有索引。
explain SELECT count(*) FROM ofRoster_par WHERE username='1';
+----+-------------+--------------+------+----------------------+----------------------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------+------+----------------------+----------------------+---------+-------+------+-------------+
| 1 | SIMPLE | ofRoster_par | ref | ofRoster_unameid_idx | ofRoster_unameid_idx | 4 | const | 120 | Using index |
+----+-------------+--------------+------+----------------------+----------------------+---------+-------+------+-------------+
explain SELECT count(*) FROM ofRoster WHERE username='1';
+----+-------------+----------+------+----------------------+----------------------+---------+-------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+------+----------------------+----------------------+---------+-------+------+--------------------------+
| 1 | SIMPLE | ofRoster | ref | ofRoster_unameid_idx | ofRoster_unameid_idx | 66 | const | 120 | Using where; Using index |
目前表上只有 400,000 条记录,但生产记录将约为 8000 万条。
两个查询所花费的时间也是相同的:-(
最佳答案
PARTITION BY HASH
在我看来,无用。
在您的示例中,非分区表上的 INDEX(username)
可能比使用 PARTITION BY HASH(username)
更快。
你已经有这样的索引了。速度有多快?
这是发生的事情:
带分区:
- 选择分区
- 使用
KEY(username)
(而不是数据)在索引内执行COUNT(*)
(注意“使用索引”)
没有分区:
- 使用
KEY(username)
(而不是数据)在索引内执行COUNT(*)
(注意“使用索引”)
其他评论:
- 如果
用户名
是唯一的,请考虑将其设为主键
并删除rosterID
。 (您可能需要保留rosterID
,因为它较小并且用于JOINing
到其他几个表。) - Bug:您说的是
INT(64)
,而您的意思是VARCHAR(64)
。这可能会影响您的计时测试。 - “前缀索引”
(jid(255))
很少有用。让我们看看您如何使用它。 - 80M 行不保证
BIGINT
(8 字节);INT UNSIGNED
(4 字节)可以处理 40 亿。 - 您知道
latin1
限制您只能使用西欧语言吗? - 当对分区表使用
EXPLAIN
时,请使用EXPLAIN PARTITIONS SELECT ...
。你可能会得到一些惊喜。
关于mysql - [索引列分区的好处],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38712320/