MD5 ক্ষেত্রের জন্য সর্বোত্তম ডেটা টাইপ কী?


35

আমরা এমন একটি সিস্টেম ডিজাইন করছি যা পঠন-ভারী হিসাবে পরিচিত (প্রতি মিনিটে কয়েক হাজার পাঠের ক্রম অনুসারে)।

  • একটি টেবিল রয়েছে namesযা কেন্দ্রীয় রেজিস্ট্রি বাছাই হিসাবে কাজ করে। প্রতিটি সারিতে একটি textক্ষেত্র representationএবং একটি অনন্য keyযা এটির একটি MD5 হ্যাশ representation1 এই সারণীতে বর্তমানে কয়েক মিলিয়ন রেকর্ড রয়েছে এবং এটি প্রয়োগের আজীবন বিলিয়নে পরিণত হবে বলে আশা করা হচ্ছে।
  • আরও কয়েক ডজন অন্যান্য সারণী রয়েছে (সর্বাধিক পরিবর্তিত হওয়া স্কিমা এবং রেকর্ড গণনাগুলির) যা namesসারণীতে রেফারেন্স দেয় । এই টেবিলগুলির মধ্যে একটিতে প্রদত্ত যে কোনও রেকর্ডের একটি অবশ্যই গ্যারান্টিযুক্ত name_key, যা কার্যত namesটেবিলে বিদেশী কী ।

1: প্রসঙ্গক্রমে, যেমনটি আপনি আশা করতে পারেন, এই টেবিলের রেকর্ডগুলি একবার লিখিত হয় ut

টেবিল ব্যতীত অন্য যে কোনও প্রদত্ত টেবিলের জন্য names, সর্বাধিক সাধারণ ক্যোয়ারী এই প্যাটার্নটি অনুসরণ করবে:

SELECT list, of, fields 
FROM table 
WHERE name_key IN (md5a, md5b, md5c...);

আমি পড়ার পারফরম্যান্সের জন্য অনুকূলিত করতে চাই আমার সন্দেহ হয় যে আমার প্রথম স্টপটি সূচকের আকারকে হ্রাস করা উচিত (যদিও আমি সেখানে ভুল প্রমাণিত হওয়ার বিষয়টি মনে করি না)।

প্রশ্ন:
/ keyএবং name_keyকলামগুলির জন্য সর্বোত্তম ডেটা কী ? ওভার
ব্যবহার করার কোনও কারণ আছে ? বা ?hex(32)bit(128)BTREEGIN

উত্তর:


41

ডাটা টাইপ uuidকরা হয় পুরোপুরি কাজের জন্য উপযুক্ত। এটির জন্য varcharবা textউপস্থাপনের জন্য র্যামের 37 বাইটের বিপরীতে কেবল 16 বাইট দখল করে । (অথবা ডিস্কে 33 বাইট, তবে বিজোড় সংখ্যার জন্য এটি 40 বাইট কার্যকরভাবে তৈরি করতে অনেক ক্ষেত্রে প্যাডিং প্রয়োজন )) এবং uuidপ্রকারটির আরও কিছু সুবিধা রয়েছে।

উদাহরণ:

SELECT md5('Store hash for long string, maybe for index?')::uuid AS md5_hash

বিশদ এবং আরও ব্যাখ্যা:

আপনি যদি এমডি 5 এর ক্রিপ্টোগ্রাফিক উপাদানটির প্রয়োজন না হন তবে আপনি অন্যান্য (সস্তার) হ্যাশিং ফাংশনগুলি বিবেচনা করতে পারেন তবে আমি আপনার ব্যবহারের ক্ষেত্রে এমডি 5 নিয়ে যাব (বেশিরভাগই কেবল পঠনযোগ্য)।

সতর্কতার শব্দ : আপনার ক্ষেত্রে ( immutable once written) কার্যকরীভাবে নির্ভরশীল (সিউডো-প্রাকৃতিক) পিকে ঠিক আছে। তবে একইরকম একটি ব্যথা হবে যেখানে আপডেটগুলি textপাওয়া সম্ভব। কোনও টাইপো সংশোধন করার কথা ভাবুন: পিকে এবং সমস্ত নির্ভরশীল সূচক, এফকে কলামগুলি dozens of other tablesএবং অন্যান্য রেফারেন্সগুলিতেও পরিবর্তন করতে হবে। সারণী এবং সূচক ব্লাট, লকিংয়ের সমস্যা, ধীর আপডেটগুলি, হারানো রেফারেন্স, ...

যদি textস্বাভাবিক অপারেশনে পরিবর্তন আসতে পারে তবে একটি সারোগেট পিকে আরও ভাল পছন্দ হবে। আমি একটি bigserialকলামের জন্য প্রস্তাব দিচ্ছি (পরিসীমা -9223372036854775808 to +9223372036854775807- এটি নয় পঞ্চাশটি দুইশ তেইশ কোয়াড্রিলিয়ন তিনশ পঁচাত্ত্বিক ট্রিলিয়ন ছত্রিশ ছয় হাজার কিছু বিলিয়ন ) এর স্বতন্ত্র মানগুলির জন্য billions of rows। যে কোনও ক্ষেত্রে একটি ভাল ধারণা হতে পারে : কয়েক হাজার এফ কলাম এবং সূচকের 16 বাইটের পরিবর্তে 8 ) 8 বা অনেক বড় কার্ডিনালিটিস বা বিতরণ সিস্টেমের জন্য একটি এলোমেলো ইউআইডি । মূল টেক্সট থেকে দ্রুত মূল টেবিলটিতে সারিগুলি সন্ধান করার জন্য আপনি সর্বদা অতিরিক্ত md5 (as ) সঞ্চয় করতে পারেন । সম্পর্কিত:uuid

আপনার জিজ্ঞাসা হিসাবে :


ড্যানিয়েলের মন্তব্যে সম্বোধন করার জন্য : আপনি যদি হাইফেন ছাড়াই উপস্থাপনা পছন্দ করেন তবে প্রদর্শনের জন্য হাইফেনগুলি সরান:

SELECT replace('90b7525e-84f6-4850-c2ef-b407fae3f271', '-', '')

তবে আমি বিরক্ত করতাম না। ডিফল্ট উপস্থাপনা ঠিক আছে। এবং সমস্যাটি এখানে সত্য উপস্থাপন নয়।

অন্য পক্ষের যদি আলাদা দৃষ্টিভঙ্গি হওয়া উচিত এবং হাইফেন ছাড়াই স্ট্রিংগুলি মিশ্রণে নিক্ষেপ করা উচিত তবে এটি কোনও সমস্যা নয়। পোস্টগ্রিস এ এর ​​ইনপুট হিসাবে বেশ কয়েকটি যুক্তিসঙ্গত পাঠ্য উপস্থাপনা গ্রহণ করে uuidডকুমেন্টেশন :

পোস্টগ্রিএসকিউএল ইনপুটগুলির জন্য নিম্নলিখিত বিকল্প ফর্মগুলিও গ্রহণ করে: উচ্চ-কেস ডিজিটের ব্যবহার, ব্রেস দ্বারা বেষ্টিত স্ট্যান্ডার্ড ফর্ম্যাট, কিছু বা সমস্ত হাইফেন বাদ দিয়ে, চার অঙ্কের কোনও গ্রুপের পরে একটি হাইফেন যুক্ত করে। উদাহরণগুলি হ'ল:

A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A11
{a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11}
a0eebc999c0b4ef8bb6d6bb9bd380a11
a0ee-bc99-9c0b-4ef8-bb6d-6bb9-bd38-0a11
{a0eebc99-9c0b4ef8-bb6d6bb9-bd380a11}

আরো কি, md5()ফাংশন আয় text, আপনি ব্যবহার করেন decode()রূপান্তর byteaএবং এর ডিফল্ট উপস্থাপনা যে হল:

SELECT decode(md5('Store hash for long string, maybe for index?'), 'hex')

\220\267R^\204\366HP\302\357\264\007\372\343\362q

encode()মূল পাঠ্য উপস্থাপনা পেতে আপনাকে আবার করতে হবে:

SELECT encode(my_md5_as_bytea, 'hex');

এটি শীর্ষে রাখতে, অভ্যন্তরীণ ওভারহেডের কারণে byteaর‌্যামে 20 বাইট (এবং ডিস্কে 17 বাইট, প্যাডিং সহ 24 ) মান হিসাবে সংরক্ষণ করা মানগুলি সাধারণ সূচকগুলির আকার এবং কার্য সম্পাদনের জন্য বিশেষত প্রতিকূল।varlena

সবকিছুuuid এখানে একটি পক্ষে কাজ করে ।


1
এই বৈধ "uuid" জন্য? দয়া করে আমি খুব বেশি পেডেন্টিক হলে আমাকে ক্ষমা করুন, তবে আমি যা মনে করি তা হ'ল "উউইডিডি" ডেটা টাইপ বাইনারি ফর্ম্যাটে দৈর্ঘ্যে ১ অক্টোট দৈর্ঘ্যের সংখ্যাগুলি সংরক্ষণ করার দিকে লক্ষ্যযুক্ত। তবে "ইউইইডি" শব্দটি একটি নির্দিষ্ট প্রজন্ম / হ্যাশিং অ্যালগরিদম পাশাপাশি ড্যাশ-বিচ্ছিন্ন হেক্সাডেসিমাল অক্ষরের 5 টি ব্লকে প্রচলিত পাঠ্য উপস্থাপনের পরামর্শ দেয়। যদি এই ধরণের নামটি ইউইউডি / জিইউডি প্রজন্মকে দৃ strongly়তার সাথে পরামর্শ দেয় তবে প্রোগ্রামারদের পক্ষে হ্যাশ সংরক্ষণের জন্য এই ধরণের ব্যবহার করা কি কিছুটা বিভ্রান্তিকর নয়?
অ্যান্ড্রু ওল্ফ

2
@ অ্যান্ড্রু ওল্ফ: সম্পূর্ণরূপে আইনী, আইএমও। নাম দিয়ে দূরে সরে যাবেন না । এটি একটি 16-বাইট সত্তা যা সরবরাহিত ধরণের কাস্ট কাস্টস এবং ইনপুট / আউটপুট যুক্তির একটি সুবিধাজনক সেট সহ। এমনকি হাতের কেসটিতে আসলে একটি "অনন্য শনাক্তকারী" প্রয়োজন। আপনি textকলামগুলিতে সমস্ত ধরণের চরিত্রের ডেটাও সংরক্ষণ করতে পারেন - এমনকি এটি কোনও "পাঠ্য" না হলেও।
এরউইন ব্র্যান্ডসেটেটার

এমডি 5 হ্যাশ যদি বেস
to৪ তে

2
@PirateApp, এটা প্রথম ডিকোড: SELECT encode(decode('tZmffOd5Tbh8yXaVlZfRJQ==', 'base64'), 'hex')::uuid;
nyov

1
@nyov: uuidএকটি 16-বাইট প্রকার যা 160 এবং 512 বিটের মধ্যে উত্পাদিত কোনও SHA অ্যালগরিদমের ফলাফল সংরক্ষণ করতে পারে না। পোস্টগ্রিসের স্ট্যান্ডার্ড বিতরণে এমন কোনও ধরণের মিল নেই। আপনি একটি তৈরি করতে পারেন ... এতে ব্যর্থ হওয়ায় , ডিফল্টরূপে bytea- যেমন পিজি_ক্রিপ্টো করেন।
এরউইন ব্র্যান্ডসটেটার

2

আমি এমডি 5 একটি textবা varcharকলামে সঞ্চয় করতাম । বিভিন্ন চরিত্রের ডেটা ধরণের মধ্যে পারফরম্যান্সের পার্থক্য নেই। আপনি সম্ভবত এমডি 5 মান varchar(xxx)নির্দিষ্ট দৈর্ঘ্যের অতিক্রম না করে তা নিশ্চিত করে এমডি 5 মানগুলির দৈর্ঘ্য সীমাবদ্ধ করতে চাইতে পারেন ।

বড় বড় তালিকা সাধারণত সত্যই দ্রুত হয় না, এর মতো কিছু করা ভাল:

with md5vals (md5) as (
  values ('one'), ('two'), ('three')
)
select t.*
from the_table t
  join md5vals m on t.name_key  = m.md5;

আরেকটি বিকল্প যা কখনও কখনও দ্রুত বলে থাকে একটি অ্যারে ব্যবহার করা:

select t.*
from the_table t
where name_key = ANY (array['one', 'two', 'three']);

যেহেতু আপনি কেবল সাম্যের জন্য তুলনা করছেন, একটি নিয়মিত বিটি ট্রি সূচক ভাল হওয়া উচিত। উভয় প্রশ্নেরই এই জাতীয় সূচকটি ব্যবহার করতে সক্ষম হওয়া উচিত (বিশেষত যদি সারিগুলির মধ্যে কেবল একটি ছোট ভগ্নাংশই নির্বাচন করা হয়।


বিট (128) বা হেক্স (32) ব্যবহার না করার কোনও বিশেষ কারণ? মানাগুলি এমন ক্ষেত্রে খুব সুন্দরভাবে ফিট করার গ্যারান্টিযুক্ত এবং আমি নির্ধারিত খারাপ মান থেকে রক্ষা করতে চাই।
ববোকপি

3
@ ববোকপি: পোস্টগ্র্রেসে কোনও "হেক্স" ডেটা টাইপ নেই। আমি কখনও bitটাইপটি ব্যবহার করি নি তাই আমি এ বিষয়ে কোনও মন্তব্য করতে পারি না। আপনার প্রত্যাশিত সংখ্যক সারি দেওয়া,
এরউইনের পরামর্শটি ইউআইডি

-1

অন্য বিকল্পটি হল 4 INTEGER বা 2 বিগিন্ট কলাম ব্যবহার করা।


2
স্টোরেজ আকারের ক্ষেত্রে, যে কোনও বিকল্প অবশ্যই মাপসই হবে তবে এটির সাথে কাজ করা কতটা সুবিধাজনক হবে? সম্ভবত আপনি একটি উদাহরণ দেখানোর জন্য আপনার উত্তরটি প্রসারিত করতে পারেন বা অন্যথায় এটি ব্যাখ্যা করতে পারেন।
অ্যান্ড্রি এম
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.