কীভাবে আলাদা আলাদা করে বাছাই করবেন?


16

কিছু সময় সিরিজের ডেটাতে আমার একটি সাধারণ নির্বাচন পৃথক রয়েছে:

SELECT DISTINCT user_id
FROM events
WHERE project_id = 6
AND time > '2015-01-11 8:00:00'
AND time < '2015-02-10 8:00:00';

এবং এটি 112 সেকেন্ড সময় নেয়। এখানে কোয়েরি পরিকল্পনাটি রয়েছে:

http://explain.depesz.com/s/NTyA

আমার অ্যাপ্লিকেশনটিতে অনেকগুলি স্বতন্ত্র ক্রিয়াকলাপ এবং এর মতো গণনা করা দরকার। এই ধরণের ডেটা পাওয়ার কি আরও দ্রুত উপায় আছে?

উত্তর:


19

আপনি সম্ভবত এটি শুনতে চান না, তবে গতি বাড়ানোর সেরা বিকল্পটি শুরু SELECT DISTINCTকরা এড়ানো DISTINCT । অনেক ক্ষেত্রে (সমস্ত নয়!) এটি আরও ভাল ডাটাবেস-ডিজাইন বা আরও ভাল ক্যোরিয়াস দিয়ে এড়ানো যেতে পারে।

কখনও কখনও, GROUP BYদ্রুত হয়, কারণ এটি একটি ভিন্ন কোড পাথ নেয়।

ইন আপনার নির্দিষ্ট ক্ষেত্রে , এটা মনে হয় না মনে হচ্ছে আপনি পরিত্রাণ পেতে পারেন DISTINCT। তবে আপনার যদি সেই ধরণের অনেক প্রশ্ন থাকে তবে আপনি বিশেষায়িত সূচকের সাহায্যে ক্যোয়ারিকে সমর্থন করতে পারেন:

CREATE INDEX foo ON events (project_id, "time", user_id);

user_idআপনি কেবলমাত্র সূচি-স্ক্যানগুলি এড়িয়ে পান তবে যোগ করা কেবলমাত্র কার্যকর । বিস্তারিত জানার জন্য লিঙ্কটি অনুসরণ করুন। আপনার ক্যোয়ারী পরিকল্পনা থেকে ব্যয়বহুল বিটম্যাপ হ্যাপ স্ক্যানটি সরিয়ে ফেলবে , যা ক্যোয়ারির 90% সময় ব্যয় করে।

আপনার EXPLAINআউটপুট আমাকে বলেছে যে কোয়েরিতে অর্ধ মিলিয়ন মিলিয়ন সারিগুলির মধ্যে 2,491 স্বতন্ত্র ব্যবহারকারীকে ঘনীভূত করতে হবে। আপনি যা-ই করুন না কেন এটি অতি দ্রুত হয়ে উঠবে না, তবে এটি যথেষ্ট দ্রুততর হতে পারে।

যদি আপনার প্রশ্নের মধ্যে সময় ব্যবধানগুলি সর্বদা একই থাকে তবে প্রতি MATERIALIIZED VIEWভাঁজটি অনেক বেশি এগিয়ে যেতে পারে। যদিও বিভিন্ন সময়ের ব্যবধানের সুযোগ নেই। হতে পারে আপনি প্রতি ঘন্টা বা অন্য কোনও ন্যূনতম সময় ইউনিটের জন্য কমপক্ষে ব্যবহারকারীদের ভাঁজ করতে পারেন এবং এটি যথেষ্ট পরিমাণে পারফরম্যান্স কিনে যথেষ্ট ওভারহেডের ওয়ারেন্ট দিতে পারে।user_id(project_id, <fixed time intervall>)

নিতপিক:
সম্ভবত, ভবিষ্যদ্বাণীগুলি "time"সত্যই হওয়া উচিত:

AND "time" >= '2015-01-11 8:00:00'
AND "time" <  '2015-02-10 8:00:00';

পাশে: সনাক্তকারী হিসাবে
ব্যবহার করবেন না time। এটি স্ট্যান্ডার্ড এসকিউএল এর একটি সংরক্ষিত শব্দ এবং পোস্টগ্রিসে একটি প্রাথমিক ধরণ।


আমি কেবল ইনডেক্সের স্ক্যানগুলি সম্পর্কে কিছুটা পড়েছি, আমি এটির শট দেব।
স্যাম

দুর্ভাগ্যক্রমে, সময় বিরতি স্থির হয় না।
স্যাম

@ সাম: তাহলে প্রস্তাবিত সূচকের সাথে আপনার উদাহরণের ক্যোয়ারীটি কতটা দ্রুত পেয়েছে?
এরউইন ব্র্যান্ডসটেটার

3
@ এডউইন: এখনও প্রোডাকশনে চেষ্টা করেননি। যাইহোক, আমি আমার স্থানীয় (একই ডেটা সহ) আসল জিজ্ঞাসাটি চালিয়েছি এবং এটি 3678.780 এমএস নিয়েছে। তারপরে আমি সূচিটি যুক্ত করেছি এবং এটি 170.156 এমএস পর্যন্ত ছড়িয়েছে। পরিকল্পনায় এখন 'ইভেন্টগুলিতে ফু ব্যবহার করে সূচক কেবল স্ক্যান' রয়েছে।
স্যাম

1
@ সাম: চমৎকার! এটাই আমি লক্ষ্য করেছিলাম।
এরউইন ব্র্যান্ডস্টেটার

2

এখানে স্যামের কেস এবং এরউইনের উত্তর সম্পর্কে আমার পরীক্ষা দেওয়া আছে

drop table t1
create table t1 (id int, user_id int, project_id int, date_time timestamp without time zone) ;

insert into t1 -- 10 million row - size="498 MB"
select row_number() over(), round(row_number() over()/1000), round(row_number() over()/100000) , date
from generate_series('2015-01-01'::date, '2016-12-01'::date,'6 seconds'::interval
) date 
limit 10000000

-- before indexing - 10000000 row - output=100 row - time=2900ms
SELECT DISTINCT user_id
FROM t1
WHERE project_id = 1
AND date_time > '2015-01-01 8:00:00'
AND date_time < '2016-12-01 8:00:00' ;

CREATE INDEX foo ON t1 (project_id, date_time, user_id); -- time process=51.2 secs -- size="387 MB"         

-- after indexing - 10000000 row - output=100 row - time= 75ms (reduce ~ 38 times)
SELECT DISTINCT user_id
FROM t1
WHERE project_id = 1
AND date_time > '2015-01-01 00:00:00'
AND date_time < '2016-12-01 00:00:00' ;

এরউইন বলেছিলেন, "আপনি সম্ভবত এটি শুনতে চান না, তবে নির্বাচন নির্বাচনকে দ্রুততর করার সর্বোত্তম বিকল্প হ'ল DISTINCT শুরু করা এড়ানো many "। আমি মনে করি তিনি সঠিক, আমাদের "স্বতন্ত্র, গোষ্ঠী অনুসারে, আদেশে বাই" (যদি থাকে) ব্যবহার করা উচিত।

আমি স্যামের কেস হিসাবে একটি পরিস্থিতির মুখোমুখি হয়েছি এবং আমি মনে করি স্যাম প্রতি মাসে ইভেন্ট টেবিলে পার্টিশনটি ব্যবহার করতে পারে। আপনি জিজ্ঞাসা করার সময় এটি আপনার ডেটার আকার হ্রাস করবে, তবে উপরের ক্যোয়ারীর পরিবর্তে কার্যকর করতে একটি ফাংশন (pl / pgsql) প্রয়োজন। ফাংশনটি কোয়েরি কার্যকর করতে উপযুক্ত পার্টিশনগুলি (শর্তের উপর নির্ভর করে) সন্ধান করবে।


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