我们有一个这样的表来保存每个用户会话的登录令牌。此表未先分区,但现在我们决定对其进行分区以提高性能,因为它包含数百万行。
CREATE TABLE `tokens` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`uid` int(10) unsigned DEFAULT NULL,
`session` int(10) unsigned DEFAULT '0',
`token` varchar(128) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
UNIQUE KEY `usersession` (`uid`,`session`),
KEY `uid` (`uid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 PARTITION BY HASH(id) PARTITIONS 101;
我们计划根据“ id ”进行分区,因为它主要用于“ 选择 ”查询和因此可以有效地进行修剪。
但问题是我们维护 (uid,session) 的唯一索引,并且分区要求参与列成为唯一索引的一部分。现在,在这种情况下, (id,uid,session) 的唯一索引没有意义(将始终是唯一的)。
无论如何都可以解决这个问题,而无需手动检查(uid,session)。
答案 0 :(得分:1)
可能您的唯一uid,sessionkey
索引会为您执行一些业务规则。
您是否依赖DBMS执行该规则?您是使用INSERT .... ON DUPLICATE KEY UPDATE...
语句,还是使用错误处理程序或其他类似的东西来处理这种唯一性?或者只是为了好的措施?
如果您依赖该唯一索引,在id
上对此表进行分区将无效。 Fugeddaboudit。
如果您可以删除该索引或删除其唯一约束,则可以继续进行分区。但是分区通常不适用于具有多个唯一键的表。
40M行表通常不够大,无法成为分区的理想选择。如果您遇到性能问题,则应调查改进索引。
编辑:如果您拥有现代硬件(多TB存储,大量RAM)和精心挑选的索引,那么分区(我相信)会更加麻烦,因为它值得。对于少于10 ** 9行的表来说,这确实很麻烦。如果您的自动增量id
值必须为BIGINT
而不是INT
数据类型(因为int.MaxValue不够大),那么'当分区开始值得考虑时。
当所有查询都根据分区键进行过滤时,它最有效。在没有分区键的情况下过滤其他条件的速度很慢。
专业提示:关于正则表达式的古老说法也适用于分区。如果解决分区问题,现在有两个问题。
答案 1 :(得分:0)
BY HASH
加速系统的案例。PRIMARY KEY
上进行分区几乎没用。AUTO_INCREMENT
id。 PK - (uid, session)
。或者它应该是(toke n)
?(uid)
是多余的,给定(uid, session)
。token
是base64,那么请将其设为ascii
或其他内容。所以,我认为这会更好地工作(更小,更快等):
CREATE TABLE `tokens` (
`uid` int(10) unsigned DEFAULT NULL,
`session` int(10) unsigned DEFAULT '0',
`token` VARBINARY(128) NOT NULL DEFAULT '',
PRIMARY KEY (token),
) ENGINE=InnoDB
您搜索了以下哪些内容?
WHERE token = ...
WHERE uid = ... AND session = ...
一个缺点是我摆脱了id
;如果其他表需要id
,则需要进行更改。