ToolDeck

เครื่องสร้าง UUID v7

สร้าง UUID v7 เรียงตามเวลาสำหรับ primary key ของฐานข้อมูล

จัดรูปแบบ

จำนวน:

UUID v7 คืออะไร?

UUID v7 คือรูปแบบ UUID รุ่นถัดไปที่กำหนดมาตรฐานใน RFC 9562 (พฤษภาคม 2024) มันเข้ารหัส timestamp Unix millisecond 48 บิตในบิตที่มีนัยสำคัญสูงสุด ตามด้วย version และ variant marker และเติมบิตที่เหลือด้วยข้อมูลสุ่มที่ cryptographically secure

เนื่องจาก timestamp อยู่ใน high bits ค่า UUID v7 จึงเรียงตามลำดับเวลา ทั้งแบบ lexicographic และตัวเลข ทำให้เป็นตัวเลือกที่ยอดเยี่ยมสำหรับ database primary key ที่ UUID แบบสุ่ม (v4) ทำให้ B-tree index แตกกระจาย

ทำไม UUID แบบสุ่มถึงทำให้ Database Index แตกกระจาย

B-tree index ที่ใช้โดย PostgreSQL, MySQL, SQLite และฐานข้อมูลส่วนใหญ่ เก็บ row เรียงตามค่า key เมื่อ insert row ใหม่ ฐานข้อมูลต้องวางมันในตำแหน่งที่ถูกต้องในต้นไม้ index

กับ UUID v4 (สุ่มทั้งหมด) การ insert ใหม่แต่ละครั้งจะลงที่ตำแหน่งสุ่มในต้นไม้ index ทำให้ฐานข้อมูลต้องอ่านและเขียน internal index page ตลอดเวลา แตก page ที่เต็มและทิ้ง page อื่นไว้ครึ่งว่าง ผลคือ index ที่แตกกระจายและบวมซึ่งทำให้ทั้งการเขียนและการอ่านช้าลงเมื่อตารางโต

UUID v7 Bit Layout

UUID v7 กว้าง 128 บิต แบ่งเป็นหกฟิลด์:

BitsFieldวัตถุประสงค์
48unix_ts_msUnix timestamp 48 บิตในหน่วย millisecond — ครองครึ่งบนทั้งหมด
4verVersion number — เสมอ 0111 (decimal 7)
12rand_aข้อมูลสุ่มที่ cryptographically secure 12 บิต
2varVariant marker — เสมอ 10 (RFC 4122 variant)
62rand_bข้อมูลสุ่มที่ cryptographically secure 62 บิต

ความแม่นยำของ timestamp คือ 1 millisecond ภายใน millisecond เดียวกัน ค่า UUID v7 เรียงตาม random suffix ไม่รับประกันว่าจะเพิ่มขึ้นเรื่อยๆ ใน sub-millisecond แต่เป็น k-sortable: ID ที่สร้างใกล้เคียงกันในเวลาจะเรียงใกล้เคียงกันใน index

UUID v7 vs UUID v1

ทั้ง UUID v1 และ UUID v7 ฝัง timestamp แต่ออกแบบต่างกันอย่างมีนัยสำคัญ:

คุณสมบัติUUID v7UUID v1
Epoch / Time BaseUnix epoch (1 ม.ค. 1970)Gregorian epoch (15 ต.ค. 1582)
ความแม่นยำของเวลา1 millisecond100 nanoseconds
เรียงลำดับได้ใช่ — k-sortable ตามการออกแบบไม่ — time field ถูกสลับใน UUID layout
ความเป็นส่วนตัวไม่รั่วข้อมูล hostฝัง MAC address ของ host ที่สร้าง
ประสิทธิภาพ DB Indexยอดเยี่ยม — insert แบบ sequential, fragmentation น้อยมากแย่ — ไม่ sequential แม้มี timestamp
มาตรฐานRFC 9562 (2024)RFC 4122 (2005)
Native Browser Supportยังไม่มี (ไม่มี crypto.randomUUID v7)ไม่มีแบบ native

สำหรับโปรเจกต์ใหม่ที่ต้องการ UUID ที่เรียงตามเวลา ให้เลือก UUID v7 แทน UUID v1 UUID v1 เป็น legacy และรั่วข้อมูล host

UUID v7 vs ULID

ULID (Universally Unique Lexicographically Sortable Identifier) แก้ปัญหาคล้ายกับ UUID v7 ต่อไปนี้คือการเปรียบเทียบ:

UUID v7
  • ตาม RFC 9562 UUID standard — เข้ากันได้กับเครื่องมือ UUID ทั้งหมด
  • รูปแบบ hex พร้อมขีดกลาง — ได้รับการยอมรับทั่วไป
  • รองรับ database UUID column แบบ native
  • 128 บิตรวม
ULID
  • Crockford Base32 encoding — 26 ตัวอักษร กระชับกว่าเล็กน้อย
  • Case-insensitive และหลีกเลี่ยงตัวอักษรที่อาจสับสน (I, L, O, U)
  • อ่านได้ง่ายกว่าสำหรับมนุษย์
  • ต้องการ library — ไม่มี native platform support

หากอยู่ในระบบนิเวศ UUID แล้ว (PostgreSQL uuid column, REST API ที่ส่ง UUID) ให้ใช้ UUID v7 หากเริ่มใหม่และต้องการ encoding ที่เป็นมิตรกับมนุษย์มากกว่า ULID เป็นทางเลือกที่สมเหตุสมผล

การใช้ UUID v7 ในฐานข้อมูล

UUID v7 ยังไม่ถูกสร้างแบบ native โดยฐานข้อมูลส่วนใหญ่ แต่สามารถเก็บใน UUID column มาตรฐานและสร้างใน application code หรือผ่าน extension:

PostgreSQL
PostgreSQL: เก็บใน column uuid Extension pg-uuidv7 เพิ่มฟังก์ชัน uuid_generate_v7() ฝั่ง server หากต้องการ DB-generated ID
MySQL / MariaDB
MySQL / MariaDB: เก็บใน column BINARY(16) หรือ CHAR(36) สร้างใน application code MySQL 8.0+ รองรับ ordered UUID ผ่าน UUID_TO_BIN(UUID(), 1) สำหรับ v1 แต่ v7 ต้องสร้างระดับ app
SQLite
SQLite: เก็บเป็น TEXT (36 ตัวอักษร) หรือ BLOB (16 bytes) สร้างใน application code การเรียง lexicographic บน TEXT ทำงานถูกต้องเพราะ UUID v7 ใช้ timestamp prefix ขนาดคงที่

ตัวอย่างโค้ด

UUID v7 ยังไม่มีใน crypto.randomUUID() ใช้ library เช่น uuidv7 (npm) จนกว่าจะมี native support:

JavaScript (browser / Node.js 20+)
function generateUuidV7() {
  const buf = new Uint8Array(16)
  crypto.getRandomValues(buf)

  const ms = BigInt(Date.now())

  // Embed 48-bit Unix ms timestamp
  buf[0] = Number((ms >> 40n) & 0xFFn)
  buf[1] = Number((ms >> 32n) & 0xFFn)
  buf[2] = Number((ms >> 24n) & 0xFFn)
  buf[3] = Number((ms >> 16n) & 0xFFn)
  buf[4] = Number((ms >> 8n)  & 0xFFn)
  buf[5] = Number(ms & 0xFFn)

  // Set version 7 (0111xxxx)
  buf[6] = (buf[6] & 0x0F) | 0x70

  // Set variant (10xxxxxx)
  buf[8] = (buf[8] & 0x3F) | 0x80

  const hex = [...buf].map(b => b.toString(16).padStart(2, '0')).join('')
  return `${hex.slice(0,8)}-${hex.slice(8,12)}-${hex.slice(12,16)}-${hex.slice(16,20)}-${hex.slice(20)}`
}

// Node.js 20+ built-in
// import { randomUUID } from 'node:crypto'  // v4 only — no v7 yet in stdlib
Python (uuid7 library)
# pip install uuid7
import uuid_extensions

uid = uuid_extensions.uuid7()
print(uid)                       # e.g. 018e2b3d-1a2b-7000-8000-abc123456789
print(uid.time)                  # Unix ms timestamp embedded in the UUID

# Or as a plain string
from uuid_extensions import uuid7str
print(uuid7str())
PostgreSQL — generate UUID v7
-- PostgreSQL 13+ extension-free implementation
CREATE OR REPLACE FUNCTION uuid_generate_v7()
RETURNS uuid
LANGUAGE sql
AS $$
  SELECT encode(
    set_bit(
      set_bit(
        overlay(
          uuid_send(gen_random_uuid())
          PLACING substring(int8send(floor(extract(epoch FROM clock_timestamp()) * 1000)::bigint) FROM 3)
          FROM 1 FOR 6
        ),
        52, 1
      ),
      53, 1
    ),
    'hex'
  )::uuid;
$$;

-- Usage as a default primary key
CREATE TABLE events (
  id uuid PRIMARY KEY DEFAULT uuid_generate_v7(),
  payload jsonb,
  created_at timestamptz DEFAULT now()
);
TypeScript — extract timestamp from UUID v7
function extractTimestamp(uuid: string): Date {
  const hex = uuid.replace(/-/g, '')
  const ms = parseInt(hex.slice(0, 12), 16)  // first 48 bits = ms timestamp
  return new Date(ms)
}

const uid = '018e2b3d-1a2b-7000-8000-abc123456789'
console.log(extractTimestamp(uid).toISOString())
// → "2024-03-15T10:22:05.259Z"

คำถามที่พบบ่อย

UUID v7 เข้ากันได้กับ UUID v4 แบบ backward ไหม?
ใช่ UUID v7 ใช้รูปแบบ wire format 128 บิต, 32 หลัก hex พร้อมขีดกลางเหมือน UUID version อื่นทั้งหมด ระบบใดก็ตามที่เก็บหรือส่ง UUID จะรับ UUID v7 ได้โดยไม่ต้องเปลี่ยนแปลง Version nibble (7) และ variant bit ระบุว่าเป็น v7 สำหรับเครื่องมือที่ตรวจสอบโครงสร้าง UUID
UUID v7 เปิดเผย timestamp ที่สร้างหรือไม่?
ใช่ — 48 บิตแรกเป็น Unix millisecond timestamp ดังนั้นใครก็ตามที่มี UUID สามารถระบุเวลาที่สร้างโดยประมาณได้ (ถึง millisecond ที่ใกล้ที่สุด) หากการเปิดเผยเวลาสร้างเป็นข้อกังวลสำหรับกรณีการใช้งานของคุณ ให้ใช้ UUID v4 แทน
สามารถใช้ UUID v7 เป็น database primary key โดยไม่มี column created_at แยกต่างหากได้ไหม?
ใช่ เนื่องจาก UUID v7 ฝัง timestamp ความแม่นยำ millisecond คุณสามารถถอดรหัสค่านั้นเพื่อรับเวลาสร้างโดยประมาณได้ อย่างไรก็ตาม เพื่อความชัดเจนและการ index ทีมส่วนใหญ่ยังคง column created_at อย่างชัดเจนและใช้ UUID v7 เฉพาะสำหรับ column ID
UUID v7 มี entropy เท่าไร?
UUID v7 มีข้อมูลสุ่ม 74 บิต (12 บิตใน rand_a + 62 บิตใน rand_b) น้อยกว่า UUID v4 ที่มี 122 บิตเล็กน้อย แต่ยังคงให้ช่วงที่ปลอดภัยจาก collision ขนาดใหญ่มากสำหรับการใช้งานจริง ความสุ่มที่ลดลงเป็น trade-off เพื่อได้ timestamp sortability
UUID v7 รองรับใน browser หรือ Node.js แบบ native ไหม?
ยังไม่รองรับ ณ ต้นปี 2025 มาตรฐาน RFC 9562 เผยแพร่เมื่อพฤษภาคม 2024 และ platform support ยังตามทัน ใช้ npm package uuidv7 ไปก่อน Native support ผ่าน crypto.randomUUID({ version: 7 }) หรือ API ที่คล้ายกันอาจมาใน browser และ Node.js รุ่นอนาคต

เครื่องมือที่เกี่ยวข้อง