2010-05-24 15 views
17

मुझे एक GUID उत्पन्न करने और स्ट्रिंग प्रस्तुति के माध्यम से सहेजने की आवश्यकता है। स्ट्रिंग प्रस्तुति जितनी छोटी हो सके उतनी छोटी होनी चाहिए क्योंकि इसका उपयोग पहले से ही लंबे यूआरएल स्ट्रिंग के हिस्से के रूप में किया जाएगा।यूआरएल-GUID/UUID का कॉम्पैक्ट प्रतिनिधित्व?

अभी, सामान्य abcd-efgh -... प्रतिनिधित्व का उपयोग करने के बजाय, मैं उत्पन्न कच्चे बाइट्स का उपयोग करता हूं और इसके बजाय बेस 64-एन्कोड का उपयोग करता हूं, जिसके परिणामस्वरूप कुछ छोटी स्ट्रिंग होती है।

लेकिन क्या इसे कम करना संभव है?

मैं कुछ विशिष्टता खोने और काउंटर रखने के साथ ठीक हूं, लेकिन सभी मौजूदा कुंजी स्कैनिंग एक विकल्प नहीं है। सुझाव?

उत्तर

13

मैंने 20 ASCII वर्णों में डेटाबेस कॉलम में एक ग्रिड लिखने के लिए एक Ascii85 एन्कोडिंग का उपयोग किया। यदि यह उपयोगी है तो मैंने सी # कोड पोस्ट किया है। विशिष्ट वर्ण सेट यूआरएल एन्कोडिंग के लिए अलग हो सकता है, लेकिन आप अपने आवेदन के अनुरूप जो भी पात्र चुन सकते हैं। यह यहां उपलब्ध है: What is the most efficient way to encode an arbitrary GUID into readable ASCII (33-127)?

8

निश्चित रूप से, 64 से अधिक आधार का उपयोग करें। आपको कस्टम वर्णमाला का उपयोग करके उन्हें एन्कोड करना होगा, लेकिन आपको कुछ और "url-safe" प्रिंट करने योग्य ASCII वर्णों को ढूंढने में सक्षम होना चाहिए।

बेस 64 8 बिट्स का उपयोग करके 6 बिट्स एन्कोड करता है, इसलिए 16 बाइट GUID मान 22 बाइट एन्कोडेड हो जाता है। आप इसे किसी चरित्र या दो से कम करने में सक्षम हो सकते हैं, लेकिन बहुत कुछ नहीं।

2

मुझे यकीन नहीं है कि यह संभव है, लेकिन आप सभी जेनरेट किए गए GUID को एक तालिका में डाल सकते हैं और यूआरएल में केवल तालिका में GUID की अनुक्रमणिका का उपयोग कर सकते हैं।

आप गाइड की लंबाई को भी कम कर सकते हैं - उदाहरण के लिए 2010 से दिनों की संख्या इंगित करने के लिए 2 बाइट्स का उपयोग करें और वर्तमान दिन की शुरुआत के बाद से मिलीसेकंड की संख्या के लिए 4 बाइट्स का संकेत दें। आपके पास एक ही मिलीसेकंड में उत्पन्न 2 GUID के लिए टकराव होगा। आप 2 और यादृच्छिक बाइट भी जोड़ सकते हैं जो इसे और भी बेहतर बना देगा।

+3

एक सूचकांक का उपयोग करते हुए हालांकि, एक यूआरएल में एक GUID डालने के उद्देश्यों में से एक को हरा दिया। GUID में बहुत अधिक डेटा है, इसलिए कोई व्यक्ति केवल एक करके संख्या में वृद्धि नहीं कर सकता है और इसे आज़मा सकता है ... लेकिन वे इसे इंडेक्स के साथ कर सकते हैं। –

1

आप इसे दूसरी दिशा से देख सकते हैं। सबसे कम संभव स्ट्रिंग प्रस्तुति का उत्पादन करें और इसे एक ग्रिड में मैप करें।

नीचे के रूप में एक परिभाषित वर्णमाला का प्रयोग कुंजी जेनरेट करें:

psuedocode में:

string RandomString(char[] alphabet, int length) 
{ 
    StringBuilder result = new StringBuilder(); 
    for (int i = 0; i < length; i++) 
    result.Append(alphabet[RandomInt(0, alphabet.Length)]); 

    return result; 
} 

आप स्ट्रिंग लंबाई < 16 रखने, तो आप बस हेक्स परिणाम सांकेतिक शब्दों में बदलना कर सकते हैं और यह Guid को पारित पार्स करने के लिए कन्स्ट्रक्टर।

+1

मुझे पता है कि यह एक पुराना विषय है, लेकिन मैंने सोचा कि मुझे यह इंगित करना चाहिए कि एक स्ट्रिंग बनाना और उसे GUID में डालना एक बहुत बुरा विचार है। यदि आप इस तरह एक छद्म-यादृच्छिक स्ट्रिंग लेना चाहते थे और विभिन्न उद्देश्यों के लिए उपयोग करते हैं, तो यह ठीक है। हालांकि, इसे एक GUID के रूप में पास करने से शायद समस्याएं पैदा हो जाएंगी। – kettch

1

सटीक एक ही समस्या के लिए नहीं, लेकिन बहुत करीब - मैंने सीआरसी 64, बेस 64 का उपयोग किया है और आपको 11 बाइट्स मिलते हैं, सीआरसी 64 का परीक्षण किया गया है (साबित नहीं हुआ) ताकि विस्तृत श्रृंखला पर डुप्लिकेट न हो तार।

और चूंकि यह परिभाषा के अनुसार 64 बिट लंबा है - आपको वह आकार मिलता है जो आधा आकार है।

मूल प्रश्न का सीधे उत्तर देने के लिए - आप CRC64 को अपने GUID के किसी भी प्रतिनिधित्व को एन्कोड कर सकते हैं।

या केवल व्यवसाय कुंजी पर सीआरसी 64 चलाएं और आपके पास 64 बिट अद्वितीय चीज होगी जिसे आप बेस 64 कर सकते हैं।

+3

सीआरसी 64 के साथ समस्या यह है कि यह उलटा नहीं है। आप यूआरआईडी को सीआरसी 64 से वापस नहीं बना सकते हैं जैसे कि आप बुद्धि 6464 कर सकते हैं। – Marko

+0

@ मार्को यह उपयोगी है अगर आप परिणामस्वरूप सीआरसी 64 भी स्टोर करते हैं। लेकिन इसकी उपयोगिता शायद बहस योग्य है। – chakrit

1

मैं इस चर्चा रोचक लगा: https://www.percona.com/blog/2014/12/19/store-uuid-optimized-way/

मूल रूप से आप 36 वर्ण लेते हैं और उन्हें द्विआधारी के 16 बाइट्स में बदल जाते हैं, लेकिन पहले तीन अस्थायी टुकड़े को सॉर्ट एक संग्रहीत प्रक्रिया का उपयोग कर:

set @uuid:= uuid(); 
select @uuid; 
+--------------------------------------+ 
| @uuid        | 
+--------------------------------------+ 
| 59f3ac1e-06fe-11e6-ac3c-9b18a7fcf9ed | 
+--------------------------------------+ 

CREATE DEFINER=`root`@`localhost` 
    FUNCTION `ordered_uuid`(uuid BINARY(36)) 
    RETURNS binary(16) DETERMINISTIC 
    RETURN UNHEX(CONCAT(SUBSTR(uuid, 15, 4),SUBSTR(uuid, 10, 4),SUBSTR(uuid, 1, 8),SUBSTR(uuid, 20, 4),SUBSTR(uuid, 25))); 

select hex(ordered_uuid(@uuid)); 
+----------------------------------+ 
| hex(ordered_uuid(@uuid))   | 
+----------------------------------+ 
| 11e606fe59f3ac1eac3c9b18a7fcf9ed | 
+----------------------------------+ 
0

(लंबे समय तक समय, लेकिन आज एक ही ज़रूरत में आया)

यूयूआईडी 128 बिट लंबा है, जो 32 हेक्स प्लस 4 हाइफ़न द्वारा दर्शाया गया है। यदि हम 64 (2^6) प्रिंट करने योग्य असीसी के शब्दकोश का उपयोग करते हैं, तो यह केवल 4 बिट्स (हेक्स की लंबाई) के 32 समूहों से 6 बिट्स के 22 समूहों में परिवर्तित करने का मामला है।

यहां एक यूयूआईडी शॉर्टनर है। मूल बिट्स खोए बिना 36 वर्ण आपको 22 मिलते हैं। सुरक्षा -

https://gist.github.com/tomlobato/e932818fa7eb989e645f2e64645cf7a5

class UUIDShortner 
    IGNORE = '-' 
    BASE6_SLAB = ' ' * 22 

    # 64 (6 bits) items dictionary 
    DICT = 'a'.upto('z').to_a + 
     'A'.upto('Z').to_a + 
     '0'.upto('9').to_a + 
     ['_', '-'] 

    def self.uuid_to_base6 uuid 
     uuid_bits = 0 

     uuid.each_char do |c| 
      next if c == IGNORE 
      uuid_bits = (uuid_bits << 4) | c.hex 
     end 

     base6 = BASE6_SLAB.dup 

     base6.size.times { |i| 
      base6[i] = DICT[uuid_bits & 0b111111] 
      uuid_bits >>= 6 
     } 

     base6 
    end 
end 

# Examples: 

require 'securerandom' 
uuid = ARGV[0] || SecureRandom.uuid 
short = UUIDShortner.uuid_to_base6 uuid 
puts "#{uuid}\n#{short}" 

# ruby uuid_to_base6.rb 
# c7e6a9e5-1fc6-4d5a-b889-4734e42b9ecc 
# m75kKtZrjIRwnz8hLNQ5hd 
संबंधित मुद्दे