অ-পূর্ণসংখ্যার প্রাথমিক কী বিবেচনা


16

প্রসঙ্গ

আমি একটি ডেটাবেস ডিজাইন করছি (PostgreSQL 9.6 এ) যা বিতরণকৃত অ্যাপ্লিকেশন থেকে ডেটা সঞ্চয় করবে। অ্যাপ্লিকেশনটির বিতরণ প্রকৃতির SERIALকারণে, সম্ভাব্য জাতি-শর্তের কারণে আমি অটো-ইনক্রিমেন্ট ইন্টিজারগুলি ( ) আমার প্রাথমিক কী হিসাবে ব্যবহার করতে পারি না ।

প্রাকৃতিক সমাধান হ'ল একটি ইউআইডি, বা বিশ্বব্যাপী অনন্য শনাক্তকারী use পোস্টগ্রিস একটি অন্তর্নির্মিত UUIDটাইপের সাথে আসে , যা একটি উপযুক্ত ফিট।

ইউইউডি-র আমার যে সমস্যাটি রয়েছে তা ডিবাগিংয়ের সাথে সম্পর্কিত: এটি একটি মানবেতর-বান্ধব স্ট্রিং। শনাক্তকারী ff53e96d-5fd7-4450-bc99-111b91875ec5আমাকে কিছুই বলেনা ACC-f8kJd9xKCd, যদিও অনন্য হওয়ার গ্যারান্টিযুক্ত না হলেও আমাকে বলে যে আমি কোনও ACCবস্তুর সাথে কাজ করছি ।

প্রোগ্রামিং দৃষ্টিকোণ থেকে, বেশ কয়েকটি পৃথক অবজেক্ট সম্পর্কিত অ্যাপ্লিকেশন প্রশ্নগুলি ডিবাগ করা সাধারণ common ধরুন প্রোগ্রামার ভুলভাবে (অর্ডার) টেবিলে কোনও ACC(অ্যাকাউন্ট) অবজেক্টের জন্য অনুসন্ধান করে ORD। একজন মানব-পঠনযোগ্য শনাক্তকারী সহ, প্রোগ্রামারটি তাত্ক্ষণিকভাবে সমস্যাটি সনাক্ত করে, ইউআইডি ব্যবহার করার সময় তিনি কী ভুল ছিল তা নির্ধারণ করতে কিছু সময় ব্যয় করতেন।

আমার ইউইউডিগুলির "গ্যারান্টিযুক্ত" স্বতন্ত্রতার প্রয়োজন নেই; আমি কি দ্বন্দ্ব ছাড়া কী জেনারেট করার জন্য কিছু রুম প্রয়োজন, কিন্তু UUID Overkill হয়। এছাড়াও, সবচেয়ে খারাপ পরিস্থিতি, সংঘর্ষের ঘটনা ঘটলে এটি বিশ্বের শেষ হবে না (ডাটাবেস এটি প্রত্যাখ্যান করে এবং অ্যাপ্লিকেশনটি পুনরুদ্ধার করতে পারে)। সুতরাং, ট্রেড-অফগুলি বিবেচিত, একটি ছোট তবে মানব-বান্ধব শনাক্তকারী আমার ব্যবহারের ক্ষেত্রে আদর্শ সমাধান হবে be

অ্যাপ্লিকেশন অবজেক্টগুলি সনাক্ত করা

আমি যে শনাক্তকারীর সাথে এসেছি তার মধ্যে নিম্নলিখিত ফর্ম্যাট রয়েছে: {domain}-{string}যেখানে {domain}অবজেক্ট ডোমেন (অ্যাকাউন্ট, অর্ডার, পণ্য) দিয়ে প্রতিস্থাপন করা হয়েছে এবং {string}এলোমেলোভাবে উত্পন্ন স্ট্রিং। কিছু ক্ষেত্রে, {sub-domain}এলোমেলো স্ট্রিংয়ের আগে একটি প্রবেশ করানো এমনকি বুদ্ধিমান হতে পারে । স্বতন্ত্রতার গ্যারান্টি দেওয়ার উদ্দেশ্যে {domain}এবং এর দৈর্ঘ্যটিকে উপেক্ষা করা যাক {string}

যদি সূচীকরণ / অনুসন্ধানের পারফরম্যান্সে সহায়তা করে তবে ফর্ম্যাটটিতে একটি নির্দিষ্ট আকার থাকতে পারে।

সমস্যাটি

জানে যে:

  • আমি পছন্দ মতো একটি প্রাথমিক বিন্যাস চাই ACC-f8kJd9xKCd
  • এই প্রাথমিক কীগুলি বেশ কয়েকটি টেবিলের অংশ হবে।
  • এই সমস্ত কীগুলি 6NF ডাটাবেসে বেশ কয়েকটি যোগ / সম্পর্কের ক্ষেত্রে ব্যবহার করা হবে।
  • বেশিরভাগ টেবিলের মাঝারি থেকে বড়-ইশ আকারের আকার হবে (গড়ে ~ 1M সারি; সর্বাধিক with 100 এম সারি)।

পারফরম্যান্স সম্পর্কে, এই কীটি সঞ্চয় করার সর্বোত্তম উপায় কী?

নীচে চারটি সম্ভাব্য সমাধান রয়েছে, তবে যেহেতু ডাটাবেসের সাথে আমার খুব কম অভিজ্ঞতা আছে আমি নিশ্চিত না যে কোনটি (যদি থাকে) সেরা।

সমাধান হিসাবে বিবেচিত

স্ট্রিং হিসাবে স্টোর ( VARCHAR)

(পোস্টগ্রিস CHAR(n)এবং এর মধ্যে কোনও পার্থক্য রাখে না VARCHAR(n), তাই আমি উপেক্ষা করছি CHAR)।

কিছু গবেষণার পরে, আমি খুঁজে পেয়েছি যে স্ট্রিং তুলনা VARCHAR, বিশেষত জয়েন অপারেশনগুলির সাথে, ব্যবহারের চেয়ে ধীর INTEGER। এটি বোধগম্য হয়, তবে এই স্কেল সম্পর্কে আমার কী চিন্তা করা উচিত?

2. বাইনারি হিসাবে স্টোর ( bytea)

পোস্টগ্র্রেসের বিপরীতে, মাইএসকিউএল এর নেটিভ UUIDটাইপ নেই। BINARY36-বাইটের পরিবর্তে 16-বাইট ক্ষেত্র ব্যবহার করে কোনও ইউআইডি কীভাবে সংরক্ষণ করবেন তা ব্যাখ্যা করার জন্য বেশ কয়েকটি পোস্ট রয়েছে VARCHAR। এই পোস্টগুলি আমাকে কীটি বাইনারি হিসাবে সংরক্ষণ করার ধারণা দিয়েছে ( byteaপোস্টগ্রিসে)।

এটি আকার বাঁচায়, তবে আমি অভিনয় নিয়ে আরও উদ্বিগ্ন concerned কোন তুলনাটি আরও দ্রুত: বাইনারি বা স্ট্রিংগুলি এমন একটি ব্যাখ্যা খুঁজতে আমার খুব ভাগ্য হয়েছিল। আমি বিশ্বাস করি বাইনারি তুলনা দ্রুত হয়। যদি সেগুলি হয়, তবে byteaসম্ভবত VARCHARপ্রোগ্রামারকে এখনই প্রতিটি সময় ডেটা এনকোড / ডিকোড করতে হয়, তার চেয়ে সম্ভবত আরও ভাল ।

আমি ভুল হতে পারি, তবে আমি উভয়ই মনে করি byteaএবং VARCHARবাই (বা চরিত্র অনুসারে) বাইট বাই বা সমতা (তুলনা) করব। এই ধাপে ধাপে তুলনা এবং "সম্পূর্ণ জিনিস" কেবল তুলনা করার কোনও উপায় আছে? (আমি এটি মনে করি না, তবে এটি চেক করতে ব্যয় করে না)।

আমি মনে করি হিসাবে সংরক্ষণ করা byteaসর্বোত্তম সমাধান, তবে আমি অবাক হচ্ছি যে অন্য কোনও বিকল্প আছে যা আমি উপেক্ষা করছি। এছাড়াও, সমাধান 1-এ আমি যে উদ্বেগ প্রকাশ করেছি ঠিক তা ধরে রেখেছে: তুলনা করার ক্ষেত্রে ওভারহেড কি যথেষ্ট যে আমাকে চিন্তিত করা উচিত?

"ক্রিয়েটিভ" সমাধান

আমি দুটি অত্যন্ত "সৃজনশীল" সমাধান নিয়ে কাজ করতে পেরেছি, আমি ঠিক জানি না কতটা পরিমাণে (অর্থাত্ যদি আমি এগুলিকে কোনও টেবিলে কয়েক হাজার সারিও বেশি করে স্কেল করতে সমস্যা করি)।

৩. UUIDতবে এটির সাথে যুক্ত "লেবেল" থাকলেও সংরক্ষণ করুন

ইউআইডিগুলি ব্যবহার না করার মূল কারণটি যাতে প্রোগ্রামাররা অ্যাপ্লিকেশনটিকে আরও ভালভাবে ডিবাগ করতে পারে। তবে যদি আমরা উভয়ই ব্যবহার করতে পারি তবে কী হবে: ডাটাবেসগুলি সমস্ত কীগুলিকে UUIDকেবলমাত্র হিসাবে সংরক্ষণ করে , তবে এটি অনুসন্ধানগুলি করার আগে / পরে বস্তুটি আবৃত করে।

উদাহরণস্বরূপ, প্রোগ্রামার এর জন্য জিজ্ঞাসা করে ACC-{UUID}, ডাটাবেস ACC-অংশটি উপেক্ষা করে , ফলাফলগুলি এনে দেয় এবং সেগুলি সমস্ত হিসাবে ফিরিয়ে দেয় {domain}-{UUID}

সঞ্চিত পদ্ধতি বা ফাংশনগুলির সাথে কিছু হ্যাকারির মাধ্যমে এটি সম্ভব হবে তবে কিছু প্রশ্ন মাথায় আসে:

  • এটি (প্রতিটি ক্যোয়ারীতে ডোমেন অপসারণ / যুক্ত করা) কি যথেষ্ট ওভারহেড?
  • এটা কি সম্ভব?

আমি এর আগে কখনও সঞ্চিত পদ্ধতি বা ফাংশন ব্যবহার করি নি, তাই এটি এমনকি সম্ভব কিনা তাও আমি নিশ্চিত নই। কেউ কি কিছু আলোকপাত করতে পারে? যদি আমি প্রোগ্রামার এবং সঞ্চিত ডেটার মধ্যে একটি স্বচ্ছ স্তর যোগ করতে পারি তবে এটি একটি নিখুঁত সমাধান বলে মনে হচ্ছে।

4. (আমার প্রিয়) আইপিভি 6 হিসাবে স্টোর cidr

হ্যাঁ, আপনি এটি ঠিক পড়েছেন। দেখা যাচ্ছে যে IPv6 ঠিকানার ফর্ম্যাটটি আমার সমস্যাটিকে পুরোপুরি সমাধান করে ।

  • আমি প্রথম কয়েকটি অক্টেটে ডোমেন এবং সাব-ডোমেন যুক্ত করতে পারি এবং বাকিগুলি এলোমেলো স্ট্রিং হিসাবে ব্যবহার করতে পারি।
  • সংঘর্ষের মতভেদ ঠিক আছ। (যদিও আমি 2 ^ 128 ব্যবহার করব না তবে এটি এখনও ঠিক আছে)
  • সমতার তুলনাগুলি (আশাকরি) অপ্টিমাইজ করা হয়েছে, সুতরাং আমি কেবল ব্যবহারের চেয়ে ভাল পারফরম্যান্স পেতে পারি bytea
  • আমি containsকীভাবে ডোমেন এবং তাদের শ্রেণিবিন্যাসকে প্রতিনিধিত্ব করে তার উপর নির্ভর করে কিছু আকর্ষণীয় তুলনা করতে পারি ।

উদাহরণস্বরূপ, ধরুন আমি 0000"পণ্য" ডোমেন উপস্থাপনের জন্য কোড ব্যবহার করি । কী 0000:0db8:85a3:0000:0000:8a2e:0370:7334পণ্যটির প্রতিনিধিত্ব করবে 0db8:85a3:0000:0000:8a2e:0370:7334

এখানে মূল প্রশ্নটি: এর সাথে তুলনা করে bytea, cidrডেটা টাইপ ব্যবহারের কোনও প্রধান সুবিধা বা অসুবিধা আছে কি?


5
কতগুলি বিতরণ নোড সম্ভব? আপনি কি তাদের নাম (এবং নাম) আগেই জানেন? আপনি কি সমন্বিত (বহুবিধ) পিকে বিবেচনা করেছেন? একটি ডোমেন (আমার প্রথম প্রশ্নের উপর নির্ভর করে), এবং একটি সরল সিরিয়াল কলামটি সবচেয়ে ছোট, সহজতম এবং দ্রুততম হতে পারে ...
এরউইন ব্র্যান্ডসটেটার

@ ফিলিল ধন্যবাদ! @ ইরভিন ব্র্যান্ডসেটটার অ্যাপ্লিকেশন সম্পর্কিত, এটি লোড অনুযায়ী অটো-স্কেল করার জন্য ডিজাইন করা হচ্ছে, সুতরাং সময়ের আগে খুব অল্প তথ্য আছে। আমি (ডোমেন, ইউআইইউডি) পিকে হিসাবে ব্যবহার করার কথা ভেবেছি, তবে এটি "ডোমেন" এর পুনরাবৃত্তি করবে, ডোমেনটি এখনও varcharঅন্য অনেক সমস্যার মধ্যে থাকবে। আমি পিজির ডোমেনগুলি সম্পর্কে জানতাম না, যা সম্পর্কে জেনে রাখা দুর্দান্ত। আমি দেখছি যে প্রদত্ত ক্যোয়ারীটি সঠিক অবজেক্টটি ব্যবহার করছে যদি ডোমেনগুলি যাচাই করতে ব্যবহৃত হয় তবে এটি এখনও একটি পূর্ণসংখ্যার সূচক না থাকার উপর নির্ভর করবে। serialএখানে ব্যবহারের কোনও "সুরক্ষিত" উপায় আছে কিনা তা নিশ্চিত নয় (একটি লক স্টেপ ছাড়াই)।
রেনাটো সিকির ম্যাসারো

1
ডোমেন অগত্যা একটি হতে হবে না varchar। এটিকে একটি FK integerপ্রকার বানানোর কথা বিবেচনা করুন এবং এর জন্য একটি সারণী যুক্ত করুন। এইভাবে আপনার উভয়ই মানব পাঠযোগ্যতা থাকতে পারে এবং আপনি আপনার যৌগিকটিকে PKসন্নিবেশ / আপডেটের অসঙ্গতিগুলি (অস্তিত্বহীন ডোমেন স্থাপন) থেকে সুরক্ষা পাবেন।
ইমেট

1
textবাঞ্ছনীয় শেষ হয়ে গেছে varchar। এ depesz.com/2010/03/02/charx-vs-varcharx-vs-varchar-vs-text এবং postgresql.org/docs/current/static/datatype-character.html
pietrop

1
আমি পছন্দ মতো একটি প্রাথমিক বিন্যাস চাই ACC-f8kJd9xKCd"← এটি ভাল পুরানো সংমিশ্রণ মূল কী জন্য একটি কাজ বলে মনে হয় ।
এমডিসিএল

উত্তর:


5

ব্যবহার ltree

যদি আইপিভি 6 কাজ করে তবে দুর্দান্ত। এটি "দুদক" সমর্থন করে না। ltreeআছে।

একটি লেবেল পাথ হ'ল শূন্য বা আরও বেশি লেবেলের ক্রম যা বিন্দু দ্বারা পৃথক করা হয়, উদাহরণস্বরূপ L1.L2.L3, শ্রেণিবদ্ধ গাছের গোড়া থেকে একটি নির্দিষ্ট নোডের জন্য একটি পথকে উপস্থাপন করে। একটি লেবেলের পাথের দৈর্ঘ্য অবশ্যই 65 কেবি এর চেয়ে কম হওয়া উচিত, তবে এটি 2 কেবি এর নীচে রাখা ভাল। বাস্তবে এটি কোনও বড় সীমাবদ্ধতা নয়; উদাহরণস্বরূপ, ডিএমওজেড ক্যাটালগের সবচেয়ে দীর্ঘ লেবেলের পাথ ( http://www.dmoz.org ) প্রায় 240 বাইট।

আপনি এটি এর মতো ব্যবহার করবেন,

CREATE EXTENSION ltree;
SELECT replace('ACC-f8kJd9xKCd', '-', '.')::ltree;

আমরা নমুনা ডেটা তৈরি করি।

SELECT x, (
  CASE WHEN x%7=0 THEN 'ACC'
    WHEN x%3=0 THEN 'XYZ'
    ELSE 'COM'
  END ||'.'|| md5(x::text)
  )::ltree
FROM generate_series(1,10000) AS t(x);

CREATE INDEX ON foo USING GIST (ltree);
ANALYZE foo;


  x  |                ltree                 
-----+--------------------------------------
   1 | COM.c4ca4238a0b923820dcc509a6f75849b
   2 | COM.c81e728d9d4c2f636f067f89cc14862c
   3 | XYZ.eccbc87e4b5ce2fe28308fd9f2a7baf3
   4 | COM.a87ff679a2f3e71d9181a67b7542122c
   5 | COM.e4da3b7fbbce2345d7772b0674a318d5
   6 | XYZ.1679091c5a880faf6fb5e6087eb1b2dc
   7 | ACC.8f14e45fceea167a5a36dedd4bea2543
   8 | COM.c9f0f895fb98ab9159f51fd0297e236d

এবং ভায়োলা ..

                                                          QUERY PLAN                                                          
------------------------------------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on foo  (cost=103.23..234.91 rows=1414 width=57) (actual time=0.422..0.908 rows=1428 loops=1)
   Recheck Cond: ('ACC'::ltree @> ltree)
   Heap Blocks: exact=114
   ->  Bitmap Index Scan on foo_ltree_idx  (cost=0.00..102.88 rows=1414 width=0) (actual time=0.389..0.389 rows=1428 loops=1)
         Index Cond: ('ACC'::ltree @> ltree)
 Planning time: 0.133 ms
 Execution time: 1.033 ms
(7 rows)

আরও তথ্য এবং অপারেটরগুলির জন্য ডক্স দেখুন

আপনি যদি আইডিটি তৈরি করে থাকেন তবে আমি ltree করব। এগুলি তৈরি করার জন্য যদি আপনার কিছু প্রয়োজন হয় তবে আমি ইউইউডি ব্যবহার করব।


1

শুধু বাইটিয়া সঙ্গে পারফরম্যান্স তুলনা সম্পর্কিত। নেটওয়ার্কের তুলনা 3 টি ধাপে করা হয়: প্রথমে নেটওয়ার্ক অংশের সাধারণ বিটগুলিতে, তারপরে নেটওয়ার্ক অংশের দৈর্ঘ্য এবং তারপরে পুরো আনমস্কড ঠিকানায়। দেখুন: নেটওয়ার্ক_সিএমপি_ আন্তঃ

সুতরাং এটি কিছুটা ধীর হওয়া উচিত তবে বাইটায় যা স্ট্রিমট মেমপ্যাম্পে চলে যায়। আমি একটি টেবিলে একটি সাধারণ পরীক্ষা চালিয়েছি যেখানে একটি মিলিয়নের জন্য সারি 10 মিলিয়ন সারি রয়েছে:

  • সংখ্যার আইডি (পূর্ণসংখ্যা) ব্যবহার করে এটি আমার 1000 মিমি নিয়েছে।
  • সিডার ব্যবহার করে এটি 1300 মিমি নিয়েছে।
  • বাইটায় ব্যবহার করে এটি 1250 মিমি নিয়েছে।

আমি বলতে পারি না বাইটিয়া এবং সিডারের মধ্যে অনেক পার্থক্য রয়েছে (যদিও ব্যবধানটি ধারাবাহিক ছিল) কেবল অতিরিক্ত ifবিবৃতি - অনুমান করুন যে এটি 10 ​​মিটার টিপলসের পক্ষে খুব খারাপ নয়।

আশা করি এটি সহায়তা করে - আপনি কী পছন্দ করেছেন তা শুনতে ভাল লাগবে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.