尝试谷歌搜索但是:
问题: 从外部生成MySQL字段的顺序UID值的最佳方法,该字段必须可以表示为字符串。
原因:
从char [0]转发中搜索字段索引时,磁盘顺序/页面附加插入的通用顺序UUID-ish值,用于执行写入和读取速度的日期前缀。该列将被索引,但寻找最佳数据以增加索引读取和表写入性能,而不是普通的UUID。
我最初的想法是在固定宽度的字段中附加或替换UUIDv4生成的字符串的某些部分(即[Unix epoch][remaining UUID4]
)的某些粒度(可能是填充的纪元)的日期,但我不确定这是否会有所需的页内/磁盘排序结果和索引搜索结果。一个例子是:
12904645950049bceba1cc24e80806dd
值必须独立于MySQL本身,因此使用UUID和时间戳而不是自动递增的某些变体。
任何知道MySQL索引内部的人都有任何建议(对于InnoDB表)?
艾登
答案 0 :(得分:5)
可能有点偏离外表,但看看Twitter's snowflake。他们说是:
更不用说其他功能(HA等)。您既可以使用算法,也可以直接使用它。
整个UID最多只使用64位空间,所以我猜测索引是非常有效的 - 请参阅http://www.mysqlperformanceblog.com/2006/10/03/long-primary-key-for-innodb-tables/(反例)。
答案 1 :(得分:3)
我认为您可能需要更具体地了解您要解决的问题(实际问题是什么?为什么不是auto_increment?,您提出的架构是什么?等等)。 回答你的内部问题:
不按顺序插入的风险至少有两倍:
如果您没有适合内存,则可能需要执行随机IO以从磁盘加载页面以将值插入该页面。
页面中可能没有剩余空间(InnoDB填充93%并且更新留下一个小间隙),这可能导致页面需要拆分。更多拆分页面=碎片/不太理想的事物使用,例如记忆。
所以,我认为只要你是近似顺序的,至少(1)不是主键索引的关注(对任何唯一索引仍然可以)。你只需要担心(2)。
为什么我说理解问题很重要,除了长GUID之外,还有很多方法可以解决这个问题。首先,MySQL中的BIGINT小于您可能使用的任何数据类型,但其范围为18 quintillion。您可以一次为工作节点分配密钥空间N 000的“块”,并保证不重复。如果一个工作节点崩溃并且没有使用它所分配的所有块,那么什么。没关系。
答案 2 :(得分:2)
查看此question。它可能没有详细说明MySQL索引的具体用法,但它确实为您提供了一些性能数据,以及生成Seq的代码。的UID。
似乎MySQL索引从顺序ID中获益很大,根据MySQL,索引依赖于磁盘排序(参见章节: B-Tree索引特征)来查找相关结果。
从内存来看,MySQL索引(至少对于String索引)依赖于字段的字母数字排序,即“哦,它以A开头?我的数据以A开头,我会获取它为你...等“而不是对每个字段进行全文扫描。
按顺序输入UID意味着索引不会首先按字母顺序对结果进行重新排序,或者至少会显着减少此时间,因此上述性能优势将得到改善。
(不是真正的解决方案,至少是答案。)
答案 3 :(得分:1)
我所做的是使用固定宽度的字符字段,并将随机UUID字符串用于当前时间(以毫秒为单位)。这很好,因为即使您的服务器在相同的毫秒内被访问两次,它仍然(可能)是唯一的。我假设如果你有一个大量服务器加载,这可能会给出多个id,但是如果你担心,你可以查看是否已经创建了一个带有这个uuid的行。
$date = new DateTime();
$UUID = uniqid( $date->format('Uu'), FALSE); // For less length
$UUID = uniqid( $date->format('Uu'), TRUE); // For more length
这是我在(很少使用的)服务器上使用的内容。但它应该对更大的负载保持强大。正如我所说,克服创建两个相同密钥的微小机会,检查它是否已被使用并分配一个新密钥。 (这不应该经常发生)