gpt4 book ai didi

ruby-on-rails - 如果我使用 GUID 作为主键,那么使用 Rails 3.1 的 COMB GUID 是个好主意吗?

转载 作者:行者123 更新时间:2023-12-04 03:49:41 24 4
gpt4 key购买 nike

我在 PostgreSQL 8.4 中使用 Rails 3.1。让我们假设我想要/需要使用 GUID 主键。一个潜在的缺点是索引碎片。在 MS SQL 中,推荐的解决方案是使用特殊的顺序 GUID。一 approach顺序 GUID 是组合 GUID,它用 6 字节时间戳替换 GUID 末尾的 MAC 地址部分。这有一些主流采用:COMB 在 NHibernate ( NHibernate/Id/GuidCombGenerator.cs ) 中本地可用。

我想我已经想出了如何在 Rails 中创建 COMB GUID(在 UUIDTools 2.1.2 gem 的帮助下),但它留下了一些悬而未决的问题:

  • 当 PRIMARY KEY 类型为 UUID 时,PostgreSQL 是否会出现索引碎片?
  • 如果 GUID 的低 6 个字节是连续的,是否可以避免碎片?
  • 下面实现的 COMB GUID 是否是在 Rails 中创建顺序 GUID 的可接受、可靠的方法?

  • 谢谢你的想法。
    create_contacts.rb移民
    class CreateContacts < ActiveRecord::Migration
    def up
    create_table :contacts, :id => false do |t|
    t.column :id, :uuid, :null => false # manually create :id with underlying DB type UUID
    t.string :first_name
    t.string :last_name
    t.string :email

    t.timestamps
    end
    execute "ALTER TABLE contacts ADD PRIMARY KEY (id);"
    end

    # Can't use reversible migration because it will try to run 'execute' again
    def down
    drop_table :contacts # also drops primary key
    end
    end
    /app/models/contact.rb
    class Contact < ActiveRecord::Base
    require 'uuid_helper' #rails 3 does not autoload from lib/*
    include UUIDHelper

    set_primary_key :id
    end
    /lib/uuid_tools.rb
    require 'uuidtools'

    module UUIDHelper
    def self.included(base)
    base.class_eval do
    include InstanceMethods
    attr_readonly :id # writable only on a new record
    before_create :set_uuid
    end
    end

    module InstanceMethods
    private
    def set_uuid
    # MS SQL syntax: CAST(CAST(NEWID() AS BINARY(10)) + CAST(GETDATE() AS BINARY(6)) AS UNIQUEIDENTIFIER)

    # Get current Time object
    utc_timestamp = Time.now.utc

    # Convert to integer with milliseconds: (Seconds since Epoch * 1000) + (6-digit microsecond fraction / 1000)
    utc_timestamp_with_ms_int = (utc_timestamp.tv_sec * 1000) + (utc_timestamp.tv_usec / 1000)

    # Format as hex, minimum of 12 digits, with leading zero. Note that 12 hex digits handles to year 10889 (*).
    utc_timestamp_with_ms_hexstring = "%012x" % utc_timestamp_with_ms_int

    # If we supply UUIDTOOLS with a MAC address, it will use that rather than retrieving from system.
    # Use a regular expression to split into array, then insert ":" characters so it "looks" like a MAC address.
    UUIDTools::UUID.mac_address = (utc_timestamp_with_ms_hexstring.scan /.{2}/).join(":")

    # Generate Version 1 UUID (see RFC 4122).
    comb_guid = UUIDTools::UUID.timestamp_create().to_s

    # Assign generted COMBination GUID to .id
    self.id = comb_guid

    # (*) A note on maximum time handled by 6-byte timestamp that includes milliseconds:
    # If utc_timestamp_with_ms_hexstring = "FFFFFFFFFFFF" (12 F's), then
    # Time.at(Float(utc_timestamp_with_ms_hexstring.hex)/1000).utc.iso8601(10) = "10889-08-02T05:31:50.6550292968Z".
    end
    end
    end

    最佳答案

    • Does PostgreSQL suffer from index fragmentation when the PRIMARY KEY is type UUID?


    是的,这是可以预料的。但是,如果您打算使用 COMB 策略,则不会发生。行将始终按顺序排列(这并不完全正确,但请耐心等待)。

    此外, native pgsql UUID 与 VARCHAR 之间的性能是 not all that different .要考虑的另一点。

    • Is fragmentation avoided if the low-order 6 bytes of the GUID are sequential?


    在我的测试中,我发现 UUID1(RFC 4122) 是连续的,在生成的 uuid 中已经添加了时间戳。但是是的,在最后 6 个字节中添加时间戳将确保排序。无论如何,这就是我所做的,因为显然已经存在的时间戳并不能保证顺序。更多关于梳子 here

    • Is the COMB GUID as implemented below an acceptable, reliable way to create sequential GUIDs in Rails?


    我没有使用 rails,但我会向你展示我是如何在 django 中做到的:
    import uuid, time

    def uuid1_comb(obj):
    return uuid.uuid1(node=int(time.time() * 1000))

    哪里 node是标识硬件地址的 48 位正整数。

    关于您的实现,使用 uuid 的主要优点之一是您可以安全地在数据库之外生成它们,因此,使用帮助类是一种有效的方法。您始终可以使用外部服务来生成 uuid,例如 snowflake ,但在这一点上可能是过早的优化。

    关于ruby-on-rails - 如果我使用 GUID 作为主键,那么使用 Rails 3.1 的 COMB GUID 是个好主意吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7747145/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com