পৃষ্ঠা এবং সারি সংখ্যাগুলিতে আমি কীভাবে সিটিডি পচন করব?


16

টেবিলের প্রতিটি সারিটিতে টাইপের একটি সিস্টেম কলাম থাকে যা সারিটির শারীরিক অবস্থান উপস্থাপন করে:ctidtid

create table t(id serial);
insert into t default values;
insert into t default values;
select ctid
     , id
from t;
সিটিডি | আইডি
: ---- | -:
(0,1) | 1
(0,2) | 2

এখানে ডিবিফিডল

ctidসর্বাধিক উপযুক্ত টাইপ (যেমন integer, bigintবা numeric(1000,0)) থেকে কেবল পৃষ্ঠা নম্বর পাওয়ার সর্বোত্তম উপায় কী ?

একমাত্র উপায় আমি মনে করতে পারেন খুব কুৎসিত হয়।


1
আইআইআরসি এটি একটি ভেক্টর টাইপ এবং আমাদের এগুলিতে অ্যাকসেসর পদ্ধতি নেই। আমি নিশ্চিত না আপনি এটি কোনও সি ফাংশন থেকে করতে পারেন কিনা। ক্রেগ নিশ্চিতভাবে বলবে :)
dezso

2
আপনি কি পয়েন্ট হিসাবে কাস্ট করতে পারেন? যেমন। select ct[0], ct[1] from (select ctid::text::point as ct from pg_class where ...) y;
বিএম

1
শিরোনামটি আপনাকে পৃষ্ঠা নম্বর এবং টিপল সূচী উভয়ের পরে থাকার পরামর্শ দেয় , পরে আপনি পৃষ্ঠা সংখ্যায় সঙ্কুচিত হন। আমি শরীরে সংস্করণ নিয়ে গিয়েছিলাম, টুপল সূচকটি একটি তুচ্ছ এক্সটেনশন।
এরউইন ব্র্যান্ডস্টেটার

উত্তর:


21
SELECT (ctid::text::point)[0]::bigint AS page_number FROM t;

তোমার বেহালার আমার সমাধান সঙ্গে।

@ বিএমএ ইতিমধ্যে একটি মন্তব্যে অনুরূপ কিছু ইঙ্গিত দিয়েছিল। এখানে একটি ...

প্রকারের জন্য যুক্তিযুক্ত

ctidটাইপ tid(টিপল শনাক্তকারী), ItemPointerসি কোডে বলা হয়। প্রতি ডকুমেন্টেশন:

এটি সিস্টেম কলামের ডেটা ধরণ ctid। একটি টিপল আইডি একটি জুড়ি ( ব্লক নম্বর , ব্লকের মধ্যে টিপল সূচক ) যা তার সারণির অভ্যন্তরে সারিটির শারীরিক অবস্থান চিহ্নিত করে।

বোল্ড জোর আমার। এবং:

( ItemPointer, এছাড়াও হিসাবে পরিচিত CTID)

একটি ব্লক স্ট্যান্ডার্ড ইনস্টলেশনগুলিতে 8 কেবিসর্বাধিক সারণির আকার 32 টিবিএটি যৌক্তিকভাবে অনুসরণ করে যে ব্লক সংখ্যায় অবশ্যই কমপক্ষে সর্বোচ্চ থাকতে হবে (@ ড্যানিয়েলের মন্তব্য অনুসারে গণনা স্থির করা):

SELECT (2^45 / 2^13)::int      -- = 2^32 = 4294967294

যা একটি স্বাক্ষরবিহীন মধ্যে মাপসই করা হবে integer। আরও তদন্তে আমি উত্স কোডে পেয়েছি যে ...

ব্লকগুলি ধারাবাহিকভাবে 0 থেকে 0xFFFFFFFE নম্বরযুক্ত

বোল্ড জোর আমার। যা প্রথম গণনার নিশ্চয়তা দেয়:

SELECT 'xFFFFFFFE'::bit(32)::int8 -- max page number: 4294967294

পোস্টগ্রিস স্বাক্ষরিত পূর্ণসংখ্যা ব্যবহার করে এবং তাই এক বিট সংক্ষিপ্ত। আমি লেখার উপস্থাপনাটি স্বাক্ষরিত পূর্ণসংখ্যাকে স্থানান্তরিত করে কিনা তা এখনও পিন করতে পারি না। যতক্ষণ না কেউ এটিকে পরিষ্কার করতে পারে, আমি ফিরে যাব bigint, যা কোনও ক্ষেত্রেই কাজ করে।

কাস্ট

নেই কোন নিবন্ধিত ঢালাই জন্য tidPostgres 9.3 টাইপ:

SELECT *
FROM   pg_cast
WHERE  castsource = 'tid'::regtype
OR     casttarget = 'tid'::regtype;

 castsource | casttarget | castfunc | castcontext | castmethod
------------+------------+----------+-------------+------------
(0 rows)

আপনি এখনও কাস্ট করতে পারেন textপোস্টগ্রিসের প্রতিটি কিছুর জন্য একটি পাঠ্য উপস্থাপনা রয়েছে :

আর একটি গুরুত্বপূর্ণ ব্যতিক্রম হ'ল "স্বয়ংক্রিয় আই / ও রূপান্তর কাস্ট", যা পাঠ্য বা অন্যান্য স্ট্রিংয়ের ধরণে বা রূপান্তর করতে কোনও ডেটা টাইপের নিজস্ব আই / ও ফাংশন ব্যবহার করে সম্পাদিত হয় সেগুলিতে স্পষ্টভাবে প্রতিনিধিত্ব করা হয় না pg_cast

পাঠ্যের উপস্থাপনাটি একটি বিন্দুর সাথে মেলে যা দুটি float8সংখ্যা নিয়ে গঠিত , castালাই নিখরচায়।

আপনি সূচক 0 কাস্ট সঙ্গে একটি বিন্দু প্রথম সংখ্যা অ্যাক্সেস করতে পারেন bigint। Voila।

কর্মক্ষমতা

আমি আপনার আসল সহ: মনে মনে আসা কয়েকটি বিকল্প অভিব্যক্তিগুলির উপর 30k সারি (5 সেরা) এর সাথে একটি টেবিলে একটি দ্রুত পরীক্ষা চালিয়েছি:

SELECT (ctid::text::point)[0]::int                              --  25 ms
      ,right(split_part(ctid::text, ',', 1), -1)::int           --  28 ms
      ,ltrim(split_part(ctid::text, ',', 1), '(')::int          --  29 ms
      ,(ctid::text::t_tid).page_number                          --  31 ms
      ,(translate(ctid::text,'()', '{}')::int[])[1]             --  45 ms
      ,(replace(replace(ctid::text,'(','{'),')','}')::int[])[1] --  51 ms
      ,substring(right(ctid::text, -1), '^\d+')::int            --  52 ms
      ,substring(ctid::text, '^\((\d+),')::int                  -- 143 ms
FROM tbl;

intbigintএখানে পরিবর্তে , বেশিরভাগ পরীক্ষার প্রয়োজনে অপ্রাসঙ্গিক। আমি এর জন্য পুনরাবৃত্তি করিনি bigint। @ জ্যাক মন্তব্য করেছেন এমন একটি ব্যবহারকারী-সংজ্ঞায়িত যৌগিক ধরণের উপর নির্মিত
কাস্ট t_tid
এর সংক্ষিপ্তসার: কাস্টিং স্ট্রিং ম্যানিপুলেশনের চেয়ে দ্রুত হতে থাকে। নিয়মিত প্রকাশগুলি ব্যয়বহুল। উপরের সমাধানটি সবচেয়ে সংক্ষিপ্ত এবং দ্রুততম।


1
ধন্যবাদ এরউইন, দরকারী স্টাফ থেকে এখানে এটা দেখে মনে হচ্ছে ctidএবং সারি পৃষ্ঠার জন্য 4 2 6 বাইট। আমি কাস্টিং সম্পর্কে চিন্তিত ছিলাম floatতবে আমি অনুমান করি আপনি এখানে যা বলছেন তা থেকে আমার দরকার নেই। দেখে মনে হচ্ছে কোনও ব্যবহারকারীর সংজ্ঞায়িত সংমিশ্রিত প্রকারটি ব্যবহার করার পরে অনেক ধীর গতির point, আপনিও কি এটি আবিষ্কার করেন?
জ্যাক বলছেন topanswers.xyz

@ জ্যাকডুগলাস: আরও তদন্তের পরে আমি আবার পড়ে গেলাম bigint। আপডেট বিবেচনা করুন।
এরউইন ব্র্যান্ডসেটেটার 21

1
@ জ্যাকডুগ্লাস: আপনার যৌগিক প্রকারের অভিনেতার ধারণাটি আমি পছন্দ করি। এটি পরিষ্কার এবং খুব ভাল সঞ্চালিত হয় - এমনকি কাস্ট করতে pointএবং পিছনে ফিরে আরও int8দ্রুত হওয়া সত্ত্বেও)। পূর্বনির্ধারিত ধরণের কাস্ট সর্বদা কিছুটা দ্রুত হবে। তুলনা করার জন্য আমি এটি আমার পরীক্ষায় যুক্ত করেছি। আমি এটা (page_number bigint, row_number integer)নিশ্চিত করতে চাই ।
এরউইন ব্র্যান্ডসেটেটার 21

1
2^40শুধুমাত্র 1TB, 32TB যা নয় 2^45, যা 2^13দেয় দ্বারা ভাগ করা হয় 2^32, তাই পৃষ্ঠার নম্বরটির জন্য প্রয়োজনীয় 32 বিট প্রয়োজনীয়।
ড্যানিয়েল ভ্যারিট

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