PostgreSQL এ সারণির সারি গণনা আবিষ্কার করার দ্রুত উপায়


107

শতাংশের গণনা করতে আমার একটি সারণীতে সারিগুলির সংখ্যা জানতে হবে। যদি মোট গণনা কিছু পূর্বনির্ধারিত ধ্রুবকের চেয়ে বেশি হয় তবে আমি ধ্রুবক মানটি ব্যবহার করব। অন্যথায়, আমি সারিগুলির প্রকৃত সংখ্যা ব্যবহার করব।

আমি ব্যবহার করতে পারি SELECT count(*) FROM table। তবে যদি আমার ধ্রুবক মান 500,000 হয় এবং আমার টেবিলে আমার 5,000,000,000 সারি রয়েছে, সমস্ত সারি গণনা করা অনেক সময় নষ্ট করবে।

আমার ধ্রুবক মানটি অতিক্রম করার সাথে সাথেই কি গণনা বন্ধ করা সম্ভব?

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

এটার মতো কিছু:

SELECT text,count(*), percentual_calculus()  
FROM token  
GROUP BY text  
ORDER BY count DESC;

5
আপনি কি প্রথম এন সারিটি বেছে নেওয়ার চেষ্টা করতে পারেননি যেখানে এন = ধ্রুবক + 1 ? যদি এটি আপনার ধ্রুবকের চেয়ে বেশি ফেরত দেয় তবে আপনি জানেন যে আপনার ধ্রুবকটি ব্যবহার করা উচিত, এবং যদি এটি ভাল না হয়?
gddc

টেবিলে আপনার কোনও পরিচয় বা অটো ইনক্রিমেন্ট ক্ষেত্র রয়েছে
স্পার্কি

1
@ স্পার্কি: সিকোয়েন্স ব্যাকড পিকেগুলিকে সুসংগত হওয়ার গ্যারান্টি দেওয়া হয় না, সারি মুছে ফেলা যায় বা বাতিল হওয়া লেনদেনের কারণে ফাঁকও থাকতে পারে।
মিউ খুব ছোট

আপনার আপডেটটি আপনার মূল প্রশ্নের সাথে বিরোধী বলে মনে হচ্ছে ... আপনার কি সারিগুলির সঠিক সংখ্যাটি জানা দরকার, বা আপনার কেবলমাত্র সঠিক সংখ্যাটি একটি চৌম্বের নীচে থাকলে জানা দরকার?
ঝাঁকুনি

1
@ রেনাটো দিনহানি কনসেইইনো: আপনি যে সঠিক সমস্যাটি সমাধান করার চেষ্টা করছেন তা ব্যাখ্যা করতে পারেন ? আমি মনে করি নীচের আমার উত্তরটি সমাধান করে যা আপনি প্রাথমিকভাবে যা বলেছিলেন তা ছিল আপনার সমস্যা। আপডেটটি এটিকে এমন দেখাচ্ছে যে আপনি গণনা (*) পাশাপাশি আরও অনেক ক্ষেত্র চান। আপনি যা করতে চেষ্টা করছেন ঠিক তা ব্যাখ্যা করতে পারলে এটি সহায়তা করবে। ধন্যবাদ।
রীতেশ

উত্তর:


224

বড় টেবিলগুলিতে সারি গণনা পোস্টগ্র্রেএসকিউএল-তে ধীর বলে পরিচিত। একটি সুনির্দিষ্ট নম্বর পেতে এটি এমভিসিসির প্রকৃতির কারণে সারিগুলির একটি সম্পূর্ণ গণনা করতে হবে । একটি উপায় নেই এই পর্যন্ত নাটকীয়ভাবে গতি যদি গণনা করে না হতে হবে সঠিক মত আপনার ক্ষেত্রে মনে করা হয়।

সঠিক গণনা পরিবর্তে ( ধীর গতিতে) বড় টেবিল সহ):

SELECT count(*) AS exact_count FROM myschema.mytable;

আপনি এটির মতো একটি কাছাকাছি অনুমান পান ( অত্যন্ত দ্রুত) ):

SELECT reltuples::bigint AS estimate FROM pg_class where relname='mytable';

অনুমানটি কতটা নিকটবর্তী তা নির্ভর করে আপনি ANALYZEযথেষ্ট চালাচ্ছেন কিনা । এটি সাধারণত খুব কাছাকাছি হয়।
দেখুন পোস্টগ্রি উইকি প্রায়শই জিজ্ঞাসিত প্রশ্নাবলী
বা গণনা (*) পারফরম্যান্সের জন্য ডেডিকেটেড উইকি পৃষ্ঠা

এখনো ভাল

পোস্টগ্রি উইকি নিবন্ধ হয় ছিল একটি বিট পঙ্কিল । এটি এই সম্ভাবনাটিকে উপেক্ষা করেছে যে একই স্ক্রিনে বিভিন্ন ডাটাবেসে একই নামের একাধিক টেবিল থাকতে পারে। তার জন্য অ্যাকাউন্ট করতে:

SELECT c.reltuples::bigint AS estimate
FROM   pg_class c
JOIN   pg_namespace n ON n.oid = c.relnamespace
WHERE  c.relname = 'mytable'
AND    n.nspname = 'myschema'

বা আরও ভাল এখনও

SELECT reltuples::bigint AS estimate
FROM   pg_class
WHERE  oid = 'myschema.mytable'::regclass;

দ্রুততর, সহজ, নিরাপদ, আরও মার্জিত। ম্যানুয়ালটি চালু করুনঅবজেক্ট আইডেন্টিফায়ার প্রকারের

ব্যবহার to_regclass('myschema.mytable')অবৈধ সারণীর নামগুলির ব্যতিক্রম এড়াতে পোস্টগ্রিস 9.4+ এ :


TABLESAMPLE SYSTEM (n) পোস্টগ্রাগেস 9.5+ এ

SELECT 100 * count(*) AS estimate FROM mytable TABLESAMPLE SYSTEM (1);

@ A_horse মন্তব্য করার মতো , SELECTকমান্ডের জন্য সদ্য যুক্ত হওয়া ধারাটি যদি পরিসংখ্যানে থাকে তবে দরকারী হতে পারেpg_class কোনও কারণে যথেষ্ট পরিমাণে বর্তমান না হয় । উদাহরণ স্বরূপ:

  • না autovacuum চলছে।
  • তাত্ক্ষণিকভাবে একটি বড় পরে INSERT বা DELETE
  • TEMPORARY টেবিল (যা দ্বারা আচ্ছাদন করা হয় না) autovacuum )।

এটি কেবল একটি এলোমেলো n % ( 1উদাহরণস্বরূপ) ব্লকগুলির নির্বাচন এবং এর মধ্যে সারিগুলি গণনা করে দেখায় । একটি বড় নমুনা ব্যয় বৃদ্ধি করে এবং ত্রুটি হ্রাস করে, আপনার বাছাই করে। নির্ভুলতা আরও বেশি কারণের উপর নির্ভর করে:

  • সারি আকার বিতরণ। যদি কোনও প্রদত্ত ব্লকটি সাধারণ সারির চেয়ে বৃহত্তর ধরে রাখে, গণনা স্বাভাবিকের চেয়ে কম হয় ইত্যাদি If
  • মৃত tuples বা ক FILLFACTOR প্রতি ব্লকের স্থান দখল করুন। অসমভাবে টেবিল জুড়ে বিতরণ করা হলে অনুমানটি বন্ধ হতে পারে।
  • সাধারণ রাউন্ডিং ত্রুটি।

বেশিরভাগ ক্ষেত্রেই অনুমানটি pg_class দ্রুত এবং আরও নির্ভুল হবে।

প্রকৃত প্রশ্নের উত্তর

প্রথমত, আমাকে সেই টেবিলের সারিগুলির সংখ্যা জানতে হবে, যদি মোট গণনাটি কোনও পূর্বনির্ধারিত ধ্রুবকের চেয়ে বেশি হয়,

এবং তা ...

... গণনাটি আমার ধ্রুবক মান পাস করার মুহুর্তে এটি সম্ভব, এটি গণনা বন্ধ করে দেবে (এবং সারি গণনা আরও বেশি জানাতে গণনা শেষ করার অপেক্ষায় থাকবে না)।

হ্যাঁ. আপনি এটি সহLIMIT একটি subquery ব্যবহার করতে পারেন :

SELECT count(*) FROM (SELECT 1 FROM token LIMIT 500000) t;

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


8
অবশেষে উন্নত প্রশ্নের সাথে পোস্টগ্রিস উইকি পৃষ্ঠা আপডেট করেছি।
এরউইন ব্র্যান্ডসটেটার

5
9.5 দিয়ে দ্রুত প্রাক্কলন হিসাবে tablesampleselect count(*) * 100 as cnt from mytable tablesample system (1);
ক্লজটি

1
@JeffWidman: এই অনুমান সকল পারেন বিভিন্ন কারণের জন্য প্রকৃত সারি গণনা থেকে বেশি হতে। অন্ততপক্ষে, মুছে ফেলা হতে পারে এরই মধ্যে ঘটেছে।
এরউইন ব্র্যান্ডসটেটার

2
@ এরউইন ব্র্যান্ডস্টেটর বুঝতে পারছেন যে এই প্রশ্নটি পুরানো, তবে আপনি যদি কোয়েরিটি সাবকিউরিতে মুড়ে ফেলে থাকেন তবে সীমাটি কি এটি কার্যকর হবে বা পুরো সাবকিউরিটি কার্যকর করা হবে তবে বাহ্যিক ক্যোয়ারীতে সীমাবদ্ধ থাকবে? SELECT count(*) FROM (Select * from (SELECT 1 FROM token) query) LIMIT 500000) limited_query;(আমি জিজ্ঞাসা করছি কারণ আমি একটি স্বেচ্ছাসেবী জিজ্ঞাসা থেকে একটি গণনা পাওয়ার চেষ্টা করছি যা এর মধ্যে ইতিমধ্যে একটি সীমাবদ্ধতা থাকতে পারে)
নিকোলাস এরডেনবার্গার

1
@ নিকোলাস এরডেনবার্গার: এটি সাবকিউয়ের উপর নির্ভর করে। পোস্টগ্রিসগুলিতে যাইহোক সীমাটির চেয়ে বেশি সারি বিবেচনা করা প্রয়োজন (যেমন ORDER BY somethingএটি কোনও সূচক ব্যবহার করতে পারে না বা সামগ্রিক ফাংশন সহ)। তা ছাড়া, কেবল সাবকোয়ারি থেকে সীমাবদ্ধ সীমিত সংখ্যক প্রক্রিয়াজাত করা হয়।
এরউইন ব্র্যান্ডসটেটার

12

আমি একবার পোস্টগ্রিজ অ্যাপে এটি চালিয়ে গিয়েছিলাম:

EXPLAIN SELECT * FROM foo;

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

Seq Scan on uids  (cost=0.00..1.21 rows=8 width=75)

আপনি rows=(\d+)যে সারিটি ফিরে আসবে তার সংখ্যার মোটামুটি অনুমান হিসাবে মানটি ব্যবহার করতে পারেন , তবে কেবলমাত্র SELECT COUNT(*)অনুমানটি যদি অনুমিত হয় তবে বলুন, আপনার প্রান্তিকের 1.5x এর চেয়ে কম (অথবা আপনি যে নম্বরটি আপনার আবেদনের জন্য বিবেচনা করুন)।

আপনার প্রশ্নের জটিলতার উপর নির্ভর করে এই সংখ্যাটি কম এবং কম নির্ভুল হয়ে উঠতে পারে। প্রকৃতপক্ষে, আমার আবেদনে, আমরা যোগ দিয়েছি এবং জটিল শর্তগুলি যোগ করার সাথে সাথে এটি এতটা ভুল হয়ে গেছে যে এটি সম্পূর্ণ মূল্যহীন, এমনকি 100 জনের মধ্যে কত সারি আমরা ফিরে এসেছি তাও জানার জন্য আমাদের সেই কৌশলটি ত্যাগ করতে হয়েছিল।

তবে যদি আপনার ক্যোয়ারীটি এত সহজ হয় যে Pg কতগুলি সারি ফিরে আসবে তার কিছু যুক্তিসঙ্গত ব্যবধানের মধ্যে ভবিষ্যদ্বাণী করতে পারে, এটি আপনার পক্ষে কাজ করতে পারে।


2

রেফারেন্স এই ব্লগ থেকে নেওয়া।

সারি গণনা জানতে আপনি নীচে ব্যবহার করতে পারেন।

Pg_class ব্যবহার:

 SELECT reltuples::bigint AS EstimatedCount
    FROM   pg_class
    WHERE  oid = 'public.TableName'::regclass;

Pg_stat_user_tables ব্যবহার:

SELECT 
    schemaname
    ,relname
    ,n_live_tup AS EstimatedCount 
FROM pg_stat_user_tables 
ORDER BY n_live_tup DESC;

কেবল দ্রুত নোট করুন যে এই পদ্ধতির কাজ করার জন্য আপনার টেবিলগুলি ভ্যাকুয়াম বিশ্লেষণ করতে হবে।
উইলিয়াম আবমা

1

ওরাকল-এ, আপনি rownumফিরে আসা সারির সংখ্যা সীমাবদ্ধ করতে ব্যবহার করতে পারেন । আমি অনুমান করছি যে অন্যান্য এসকিউএলগুলিতেও অনুরূপ নির্মাণ উপস্থিত রয়েছে। সুতরাং, উদাহরণস্বরূপ, আপনি দিয়েছেন, আপনি ফিরে আসা সারিগুলির সংখ্যা 500001 এ সীমাবদ্ধ করতে পারেন এবং count(*)তারপরে একটি প্রয়োগ করতে পারেন :

SELECT (case when cnt > 500000 then 500000 else cnt end) myCnt
FROM (SELECT count(*) cnt FROM table WHERE rownum<=500001)

1
সারণী গণনা (*) সিএনটি থেকে সারণি সর্বদা একটি একক সারিতে ফিরে আসবে। নিশ্চিত না কীভাবে এলএমটি সেখানে কোনও সুবিধা যুক্ত করবে।
ক্রিস বেদনারস্কি

@ ক্রিসবেডনার্স্কি: আমি আমার উত্তরের ওরাকল সংস্করণটি ওরাকল ডিবিতে যাচাই করেছি। এটি দুর্দান্ত কাজ করে এবং count(*)ওপির সমস্যাটি যা আমি ভেবেছিলাম তা সমাধান করে ( রোউনাম সহ ০.০৫ এস , রোমনাম ব্যবহার না করে ১ টি)। হ্যাঁ, SELECT count(*) cnt FROM tableসর্বদা 1 সারিটি ফিরতে চলেছে, তবে সীমাবদ্ধ শর্তের সাথে, টেবিলের আকার যখন 500000 এর বেশি হবে তখন এটি "500001" এবং টেবিলের আকার যখন <= 500000 হবে তখন ফিরে আসবে
রিতেশ

2
আপনার পোস্টগ্রিজ এসকিউএল ক্যোয়ারী সম্পূর্ণ বোকা। সিনট্যাক্টিক্যালি এবং লজিক্যালি ভুল। দয়া করে এটি সংশোধন করুন বা অপসারণ করুন।
এরউইন ব্র্যান্ডসটেটার

@ এরউইন ব্র্যান্ডসটেটার: সরানো হয়েছে, বুঝতে পারিনি পোস্টগ্র্রেএসকিউএল এত আলাদা ছিল didn't
রীতেশ

@ অলরাইট: সন্দেহ নেই আপনার ওরাকল ক্যোয়ারী ঠিকঠাক কাজ করে। LIMIT যদিও আলাদাভাবে কাজ করে works একটি প্রাথমিক স্তরে, এটি ক্লায়েন্টকে ফিরে আসা সারিগুলির সংখ্যা সীমাবদ্ধ করে, ডাটাবেস ইঞ্জিন দ্বারা অনুসন্ধান করা সারিগুলির সংখ্যা নয়।
ক্রিস বেদনারস্কি

0

পাঠ্য কলামটি কত প্রশস্ত?

কোনও গ্রুপের মাধ্যমে আপনি কোনও ডেটা স্ক্যান এড়াতে (কমপক্ষে একটি সূচক স্ক্যান) এড়াতে পারবেন না।

আমি সুপারিশ করব:

  1. সম্ভব হলে, পাঠ্য ডেটারের সদৃশতা অপসারণের জন্য স্কিমা পরিবর্তন করা। এইভাবে গণনাটি 'অনেকগুলি' সারণীতে একটি সংকীর্ণ বিদেশী কী ক্ষেত্রে প্রদর্শিত হবে।

  2. বিকল্পভাবে, পাঠ্যের একটি হ্যাশ দিয়ে একটি উত্পন্ন কলাম তৈরি করা হচ্ছে, তারপরে হ্যাশ কলামের মাধ্যমে গ্রুপ করুন। আবার, এটি কাজের চাপ হ্রাস করতে হবে (একটি সরু কলাম সূচীর মাধ্যমে স্ক্যান)

সম্পাদনা:

আপনার মূল প্রশ্নটি আপনার সম্পাদনার সাথে মেলে না। আমি নিশ্চিত নন যে আপনি যদি অবগত হন যে COUNT, যখন কোনও গ্রুপ দ্বারা ব্যবহৃত হবে, তখন প্রতি গ্রুপ অনুসারে আইটেমের গণনা ফিরিয়ে দেবে, পুরো টেবিলের আইটেমের গণনা নয়।


0

আপনি নীচের ক্যোয়ারী (* বা কোনও কলামের নাম ছাড়াই) দ্বারা গণনাটি পেতে পারেন।

select from table_name;

2
এটি এর চেয়ে দ্রুততর বলে মনে হয় না count(*)
সানি

-3

এসকিউএল সার্ভারের জন্য (2005 বা ততোধিক) একটি দ্রুত এবং নির্ভরযোগ্য পদ্ধতিটি হ'ল:

SELECT SUM (row_count)
FROM sys.dm_db_partition_stats
WHERE object_id=OBJECT_ID('MyTableName')   
AND (index_id=0 or index_id=1);

Sys.dm_db_partition_stats সম্পর্কিত বিশদ বিবরণ ব্যাখ্যা করা আছে দুটিই MSDN

ক্যোয়ারী একটি (সম্ভবত) পার্টিশনযুক্ত টেবিলের সমস্ত অংশ থেকে সারি যুক্ত করে।

index_id = 0 একটি আনর্ডারড টেবিল (হিপ) এবং সূচি_আইড = 1 একটি আদেশযুক্ত টেবিল (ক্লাস্টারড ইনডেক্স)

এমনকি দ্রুত (তবে অবিশ্বস্ত) পদ্ধতিগুলি এখানে বিশদ

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