代码之家  ›  专栏  ›  技术社区  ›  Aiden Bell

mysql char()或其他字段的顺序uid集生成

  •  5
  • Aiden Bell  · 技术社区  · 14 年前

    尝试谷歌搜索,但:

    问题 : 外部为MySQL字段生成顺序uid值的最佳方法,该字段必须表示为字符串。

    原因:
    从char[0]forward中搜索字段索引时,磁盘上的顺序/页面附加插入的通用UUID ISH值用于写入性能和读取速度的日期前缀。该列将被索引,但要查找最佳数据以提高索引读取和表写入性能,而不是简单的旧UUID。

    我最初的想法是在Uuidv4生成的字符串ie的某些部分之后附加或替换某些粒度(可能是填充的epoch)。 [Unix epoch][remaining UUID4] 在固定宽度的char字段中,但我不确定这是否具有所需的页面/磁盘排序结果和索引搜索结果。例如:

    12904645950049bceba1cc24e80806dd

    这些值必须独立于MySQL本身,因此使用UUID和时间戳,而不是一些自动递增的变体。

    有谁知道mysql索引的内部结构有什么建议(对于innodb表)?

    艾登

    4 回复  |  直到 14 年前
        1
  •  5
  •   mindas    14 年前

    可能有点离题,但请看一下 Twitter's snowflake . 他们说是:

    • (大致)时间顺序(有助于避免昂贵的随机主键btree更新)
    • 可直接分拣
    • 契约

    更不用说其他功能(HA等)。你要么刻划他们的算法,要么就按原样使用它。

    整个uid最多只占用64位空间,因此我想索引是非常有效的-请参阅 http://www.mysqlperformanceblog.com/2006/10/03/long-primary-key-for-innodb-tables/ (反例)。

        2
  •  3
  •   Morgan Tocker    14 年前

    我认为你可能需要更具体地说明你要解决的问题(实际问题是什么-为什么不自动增加?,您建议的模式是什么?等等)。 要回答您的内部问题:

    • InnoDB将数据存储在16K页的索引(聚集索引)中。

    不按顺序插入的风险至少有两倍:

    1. 如果内存不足,则可能需要执行随机IO以从磁盘加载页面以将值插入该页面。

    2. 页面中可能没有剩余空间(innodb填充93%,留下一个小的更新空间),这可能导致页面需要拆分。更多拆分页面=碎片化/对内存等事物的最佳使用率较低。

    所以,我认为只要您大致是连续的,那么至少(1)不需要考虑主键索引(对于任何唯一索引都可能是这样)。你只需要担心(2)。


    我为什么说理解这个问题很重要,是除了长相外还有很多方法可以做到这一点。例如,MySQL中的bigint比您可能使用的任何数据类型都要小,但其范围为18 Quintillion。您可以一次为工作节点分配N千个密钥空间的“块”,并保证不重复。如果一个工作节点崩溃,并且没有使用它分配的所有块,那又是什么呢?没关系。

        3
  •  2
  •   Community CDub    8 年前

    看看这个 question . 它可能没有详细说明MySQL索引的具体用途,但它确实提供了一些性能数据和生成seq的代码。UIDS。

    MySQL索引似乎从顺序ID中受益匪浅,并且 MySQL 索引依赖于磁盘顺序(请参见: B-树指数特征 )找到相关的结果。

    从内存来看,MySQL索引(至少对于字符串索引)首先依赖于字段的字母数字顺序,即“哦,它以a开头?我有一个以A开头的数据,我会帮你取的…而不是对每个字段进行全文扫描。

    并且按顺序输入uid意味着索引不会首先“按字母顺序”对结果重新排序,或者至少会显著减少这一时间,因此上面提到的性能优势。

    (不是真正的解决方案,但至少是一个答案。)

        4
  •  1
  •   Youarefunny    14 年前

    我要做的是使用一个固定宽度的字符字段,并将一个随机的UUID字符串垂直于当前时间(毫秒)。这很好,因为即使您的服务器在同一毫秒内被访问两次,它仍然(可能)是唯一的。我想如果你有 大量的 服务器加载这可能会提供多个ID,但如果担心这一点,您可以检查是否已经创建了具有此UUID的行。

    PHP:

    $date = new DateTime();
    $UUID = uniqid( $date->format('Uu'), FALSE);  // For less length
    $UUID = uniqid( $date->format('Uu'), TRUE);   // For more length
    

    这是我在(很少使用)服务器上使用的。但对于更大的负载来说,它应该能够承受更大的负载。如我所说,为了克服创建两个相同的键的微小可能性,请检查它是否已被使用,并分配一个新的键。(这种情况不应该太频繁)