मेरा उत्तर @ संतोष के उत्तर का अद्यतन है। मैं यहां वर्णित सभी सर्वोत्तम प्रथाओं को शामिल कर रहा हूं:
- https://www.percona .com/blog/2014/12/19/store-uuid-optimized-way/
- http://mysqlserverteam.com/storing-uuid-values -इन-mysql-टेबल/
मैं simple_uuid
. का उपयोग कर रहा हूं मणि क्योंकि यह "v1" UUIDs उत्पन्न कर सकता है। रूबी का बिल्ट-इन SecureRandom.uuid
v4 उत्पन्न करता है। हमें v1 की आवश्यकता है, क्योंकि यही वह है जो UUID के हिस्से के रूप में टाइमस्टैम्प को शामिल करता है। गहराई से समझने के लिए ऊपर दिए गए लिंक पढ़ें। MySQL का UUID()
फ़ंक्शन v1 UUIDs उत्पन्न करता है।
ऐप्लिकेशन/मॉडल/चिंताएं/बाइनरी_यूयूआईडी_पीके.आरबी
module BinaryUuidPk
extend ActiveSupport::Concern
included do
before_validation :set_id, on: :create
validates :id, presence: true
end
def set_id
uuid_object = SimpleUUID::UUID.new
uuid_string = ApplicationRecord.rearrange_time_of_uuid( uuid_object.to_guid )
uuid_binary = ApplicationRecord.id_binary( uuid_string )
self.id = uuid_binary
end
def uuid
self[:uuid] || (id.present? ? ApplicationRecord.format_uuid_with_hyphens( id.unpack('H*').first ).upcase : nil)
end
module ClassMethods
def format_uuid_with_hyphens( uuid_string_without_hyphens )
uuid_string_without_hyphens.rjust(32, '0').gsub(/^(.{8})(.{4})(.{4})(.{4})(.{12})$/, '\1-\2-\3-\4-\5')
end
def rearrange_time_of_uuid( uuid_string )
uuid_string_without_hyphens = "#{uuid_string[14, 4]}#{uuid_string[9, 4]}#{uuid_string[0, 8]}#{uuid_string[19, 4]}#{uuid_string[24..-1]}"
ApplicationRecord.format_uuid_with_hyphens( uuid_string_without_hyphens )
end
def id_binary( uuid_string )
# Alternate way: Array(uuid_string.downcase.gsub(/[^a-f0-9]/, '')).pack('H*')
SimpleUUID::UUID.new( uuid_string ).to_s
end
def id_str( uuid_binary_string )
SimpleUUID::UUID.new( uuid_binary_string ).to_guid
end
# Support both binary and text as IDs
def find( *ids )
ids = [ids] unless ids.is_a?( Array )
ids = ids.flatten
array_binary_ids = ids.each_with_object( [] ) do |id, array|
case id
when Integer
raise TypeError, 'Expecting only 36 character UUID strings as primary keys'
else
array << SimpleUUID::UUID.new( id ).to_s
end
end
super( array_binary_ids )
end
end
end
ऐप्लिकेशन/मॉडल/application_record.rb
## ApplicationRecord (new parent of all models in Rails 5)
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
include BinaryUuidPk
end
अब, सभी मॉडल अनुकूलित यूयूआईडी प्राथमिक कुंजियों का समर्थन करेंगे।
नमूना स्थानांतरण
class CreateUserProfiles < ActiveRecord::Migration[5.0]
def change
create_table :user_profiles, id: false do |t|
t.binary :id, limit: 16, primary_key: true, null: false
t.virtual :uuid, type: :string, limit: 36, as: "insert( insert( insert( insert( hex(id),9,0,'-' ), 14,0,'-' ), 19,0,'-' ), 24,0,'-' )"
t.index :uuid, unique: true
t.string :name, null: false
t.string :gender, null: false
t.date :date_of_birth
t.timestamps null: false
end
execute <<-SQL
CREATE TRIGGER before_insert_user_profiles
BEFORE INSERT ON user_profiles
FOR EACH ROW
BEGIN
IF new.id IS NULL THEN
SET new.id = UUID_TO_BIN(uuid(), 1);
END IF;
END
SQL
end
end
UUID_TO_BIN()
MySQL DB के लिए कार्य करें :
DELIMITER //
CREATE FUNCTION UUID_TO_BIN(string_uuid BINARY(36), swap_flag INT)
RETURNS BINARY(16)
LANGUAGE SQL DETERMINISTIC CONTAINS SQL SQL SECURITY INVOKER
RETURN
UNHEX(CONCAT(
SUBSTR(string_uuid, 15, 4),
SUBSTR(string_uuid, 10, 4),
SUBSTR(string_uuid, 1, 8),
SUBSTR(string_uuid, 20, 4),
SUBSTR(string_uuid, 25) ));
//
DELIMITER ;
उपरोक्त फ़ंक्शन MySQL 8.0 और इसके बाद के संस्करण में अंतर्निहित है। लेखन के समय, 8.0 अभी तक GA नहीं है। इसलिए, मैं अभी के लिए फ़ंक्शन जोड़ रहा हूं। लेकिन मैंने फ़ंक्शन हस्ताक्षर को वही रखा है जो MySQL 8.0 में है। इसलिए, जब हम 8.0 पर चले जाते हैं, तब भी हमारे सभी माइग्रेशन और ट्रिगर काम करते रहेंगे।