【问题标题】:Efficient/Scalable way to store and retrieve UUID as binary on MySQL在 MySQL 上以二进制形式存储和检索 UUID 的高效/可扩展方式
【发布时间】:2020-10-25 08:23:13
【问题描述】:

我使用 UUID 作为 MySQL 上表的 PK (BINARY(16))。哪个选项更好地将二进制文件转换为 UUID 字符串/从 UUID 字符串转换?

第一个选项是使用 MySQL 内置函数 UUID_TO_BINBIN_TO_UUID。这是最容易处理 UUID/二进制转换的方法。但我想它可能会在某些时候导致性能问题。

第二个选项是在应用层 (Node.js) 上运行转换。这样,由于 Web 服务器是水平可扩展的,因此性能不会成为大问题。但是,代码可能会有点混乱。

根据我的研究,Postgres 可以很好地处理 UUID。 MySQL 性能是否与 Postgres 一样好,无需担心性能?


每种方法的代码如下所示。

MySQL

INSERT INTO mytable SET id = UUID_TO_BIN("709fe2ce-be43-11ea-a4e2-784f439a6382", 1);

SELECT BIN_TO_UUID(id, 1) as id FROM mytable WHERE id = UUID_TO_BIN("709fe2ce-be43-11ea-a4e2-784f439a6382", 1);

应用程序(带 knex 的 Node.js)

async function add(data: DataType): Promise<void> {
  await knex("mytable").insert({
    ...data,
    id: toBinaryUUID(data.uuid),
  });
}

async function find(uuid: string): Promise<DataType | undefined> {
  const query = knex
    .select("id")
    .from("mytable")
    .where("id", toBinaryUUID(uuid));

  const record = await query.first();

  if (record) {
    record.id = fromBinaryUUID(record.id);
  }

  return record;
}

(我使用odo-network/binary-uuid作为转换函数。)

function fromBinaryUUID(buf: Buffer): string {
  return [
    buf.toString("hex", 4, 8),
    buf.toString("hex", 2, 4),
    buf.toString("hex", 0, 2),
    buf.toString("hex", 8, 10),
    buf.toString("hex", 10, 16),
  ].join("-");
}

function toBinaryUUID(uuid: string): Buffer {
  const buf = Buffer.from(uuid.replace(/-/g, ""), "hex");
  return Buffer.concat([
    buf.slice(6, 8),
    buf.slice(4, 6),
    buf.slice(0, 4),
    buf.slice(8, 16),
  ]);
}

【问题讨论】:

    标签: mysql node.js uuid knex.js


    【解决方案1】:

    在 MySQL 8 中,应该使用这些函数。

    • 16 个字节优于 36 个字符(空格等)
    • 函数重新排列位,以便大约同时创建的 uuid 在表中彼此“接近”。这提供了参考的时间局部性,从而加快了重要类别的查询。
    • 手动转换例程可以但可能不会重新排列位。
    • 只有类型 1 的 uuid 从重新排列中受益,但这是 MySQL 使用的类型。
    • 如果您的 uuid 来自其他地方,则重新排列不会造成伤害,但可能无济于事。
    • 如果您使用的不是 MySQL 8.0,这些例程不是内置的,但可以在下面的链接中找到。
    • 在 MySQL 8.0 中,将 swap_flag(第二个参数)包含为 1

    更多讨论:http://mysql.rjweb.org/doc.php/uuid

    【讨论】:

    • 感谢您的回答。您是否认为调用BIN_TO_UUID 会产生开销并影响性能?
    • @senta - 任何函数调用本身的开销都很低。除非重新排列位,否则较大表中的 UUID 本质上会导致高开销。看我的博客。另请参阅术语“sargeable”,它不适用于您的示例。
    • 我浏览了您的博文。我想现在我对 UUID 有了一些理解。非常感谢您提供有关 SO 和您的博客的信息。
    猜你喜欢
    • 1970-01-01
    • 2017-09-22
    • 1970-01-01
    • 2011-10-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多