Han*_*ans 5 mysql database-partitioning
我有一个非常大的 5 亿行表,其中包含以下列:
id- Bigint- 自动增加主索引。date- Datetime- 每个日期大约 150 万行,删除 1 年之前的数据。uid- VARCHAR(60)- 一个用户IDsessionNumber —— INTstart- INT- 开始时间的纪元。end- INT- 结束时间的时代。 的组合uid和sessionNumber形成uinque索引。我也有一个日期索引。
由于规模庞大,我想对表进行分区。
我的大多数访问都是按日期进行的,因此按日期范围分区似乎很直观,但由于日期不是唯一索引的一部分,因此这不是一个选项。
选项 1:RANGE PARTITION在日期和BEFORE INSERT TRIGGER
我真的没有经常遇到违反uid和sessionNumber唯一性的问题。源数据是一致的,但可以连续两天插入跨越两天的会话,午夜是第一天的结束时间和第二天的开始时间。
我试图了解是否可以删除唯一键并使用触发器
但是,我不确定是否可以 1) 在同一张表上触发更新。或 2) 防止实际插入。
选项 2:LINEAR HASH PARTITION开UID
我的第二个选择是在 UID 上使用线性哈希分区。但是,我看不到任何使用 VARCHAR 并将其转换为用于HASH分区的 INTEGER 的示例。
但是,我找不到从 VARCHAR 转换为 INTEGER 的允许方法。例如
ALTER TABLE mytable
PARTITION BY HASH (CAST(md5(uid) AS UNSIGNED integer))
PARTITIONS 20
Run Code Online (Sandbox Code Playgroud)
返回不允许分区函数。
HASH 分区必须使用 32 位整数。但是你不能简单地将 MD5 字符串转换为整数CAST()。
除了 MD5,CRC32()可以采用任意字符串并转换为 32 位整数。但这也不是一个有效的分区函数。
mysql> alter table v partition by hash(crc32(uid));
ERROR 1564 (HY000): This partition function is not allowed
Run Code Online (Sandbox Code Playgroud)
您可以使用KEY Partitioning而不是 HASH 分区按字符串进行分区。KEY 分区接受字符串。它通过 MySQL 的内置 PASSWORD() 函数传递任何输入字符串,该函数基本上与 SHA1 相关。
但是,这会导致您的分区策略出现另一个问题:
mysql> alter table v partition by key(uid);
ERROR 1503 (HY000): A PRIMARY KEY must include all columns in the table's partitioning function
Run Code Online (Sandbox Code Playgroud)
您的表的主键id不包括uid您要作为分区依据的列。这是MySQL 分区的限制:
表上的每个唯一键都必须使用表分区表达式中的每一列。
这是我正在测试的表格(将它包含在您的问题中对您来说是个好主意):
CREATE TABLE `v` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`date` datetime NOT NULL,
`uid` varchar(60) NOT NULL,
`sessionNumber` int(11) NOT NULL,
`start` int(11) NOT NULL,
`end` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uid` (`uid`,`sessionNumber`),
KEY `date` (`date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Run Code Online (Sandbox Code Playgroud)
在继续之前,我必须想知道您为什么要使用分区?“绝对大小”不是对表进行分区的理由。
与任何优化一样,分区是为了您想要优化的特定查询而完成的。任何优化都以牺牲其他查询为代价来改进一个查询。优化与表无关。桌子很高兴坐在那里有 50 亿行,它不在乎。优化是针对查询的。
因此,您需要知道要针对哪些查询进行优化。然后决定一个策略。对于需要优化的查询集,分区可能不是最佳策略!
| 归档时间: |
|
| 查看次数: |
4768 次 |
| 最近记录: |