এটি পরিস্থিতি এবং সঠিক প্রয়োজনীয়তার উপর নির্ভর করে। প্রশ্নের আমার মন্তব্য বিবেচনা করুন ।
সহজ সমাধান
সঙ্গে DISTINCT ON
Postgres মধ্যে:
SELECT DISTINCT ON (i.good, i.the_date)
i.the_date, p.the_date AS pricing_date, i.good, p.price
FROM inventory i
LEFT JOIN price p ON i.good = p.good AND i.the_date >= p.the_date
ORDER BY i.good, i.the_date, p.the_date DESC;
আদেশ ফল।
বা NOT EXISTS
স্ট্যান্ডার্ড এসকিউএল সহ (আমার পরিচিত প্রতিটি আরডিবিএমএসের সাথে কাজ করে):
SELECT i.the_date, p.the_date AS pricing_date, i.good, i.quantity, p.price
FROM inventory i
LEFT JOIN price p ON p.good = i.good AND p.the_date <= i.the_date
WHERE NOT EXISTS (
SELECT 1 FROM price p1
WHERE p1.good = p.good
AND p1.the_date <= i.the_date
AND p1.the_date > p.the_date
);
একই ফলাফল, কিন্তু ব্যাপারে খেয়ালখুশীমত সাজানোর ক্রম - যদি না আপনি যোগ ORDER BY
।
ডেটা বিতরণ, সঠিক প্রয়োজনীয়তা এবং সূচকগুলির উপর নির্ভর করে এর যেগুলির একটিতে দ্রুততর হতে পারে।
সাধারণত, DISTINCT ON
বিজয়ী এবং আপনি এটির উপরে একটি সাজানো ফলাফল পান। তবে নির্দিষ্ট কিছু ক্ষেত্রে অন্যান্য প্রশ্নের কৌশলগুলি (অনেক) দ্রুত, তবুও। নিচে দেখ.
সর্বোচ্চ / মিনিটের মানগুলি গণনা করতে সাবকিউরিয়াস সহ সমাধানগুলি সাধারণত ধীর হয়। সিটিই সহ ভেরিয়েন্টগুলি সাধারণত ধীর, তবুও।
সরল দর্শন (যেমনটি অন্য উত্তর দ্বারা প্রস্তাবিত) পোস্টগ্র্রেসের ক্ষেত্রে পারফরম্যান্সে মোটেই সহায়তা করে না।
এসকিউএল ফিডল।
সঠিক সমাধান
স্ট্রিং এবং কোলেশন
প্রথমত, আপনি একটি উপ-অনুকূল টেবিল বিন্যাস থেকে ভোগেন। এটি তুচ্ছ মনে হতে পারে তবে আপনার স্কিমাকে সাধারনকরণ করা আরও অনেক বেশি যেতে পারে।
চরিত্রের ধরণের অনুসারেtext
varchar
বাছাই করা ( ,, ...) স্থানীয় অনুসারে করা উচিত - বিশেষত COLLATION । সম্ভবত আপনার ডিবি স্থানীয় নিয়মের কিছু সেট ব্যবহার করে (যেমন, আমার ক্ষেত্রে de_AT.UTF-8
:)। এর সাথে সন্ধান করুন:
SHOW lc_collate;
এটি বাছাই এবং সূচক চেহারা আপকে ধীর করে তোলে । আপনার স্ট্রিংগুলি (পণ্যগুলির নাম) আরও খারাপ। আপনি যদি নিজের আউটপুটে (বা সাজানোর ক্রমটি মোটেই সাজিয়ে তোলেন) নিয়মের জন্য যত্নবান না হন তবে আপনি যুক্ত করলে এটি আরও দ্রুত হতে পারে COLLATE "C"
:
SELECT DISTINCT ON (i.good COLLATE "C", i.the_date)
i.the_date, p.the_date AS pricing_date, i.good, p.price
FROM inventory i
LEFT JOIN price p ON i.good = p.good AND i.the_date >= p.the_date
ORDER BY i.good COLLATE "C", i.the_date, p.the_date DESC;
আমি কীভাবে দুটি স্থানে কোলেশন যুক্ত করেছি তা নোট করুন।
আমার পরীক্ষায় দু'বার দ্রুত 20 কে সারি এবং প্রতিটি মৌলিক নাম ('গুড 123') দিয়ে দ্বিগুণ
সূচক, সূচিপত্র
যদি আপনার ক্যোয়ারীটি একটি সূচক ব্যবহার করার কথা মনে করে, অক্ষর ডেটাযুক্ত কলামগুলিতে একটি ম্যাচিং কোলেশন ব্যবহার করতে হবে ( good
উদাহরণস্বরূপ):
CREATE INDEX inventory_good_date_desc_collate_c_idx
ON price(good COLLATE "C", the_date DESC);
এসও সম্পর্কিত এই সম্পর্কিত উত্তরের শেষ দুটি অধ্যায়টি পড়তে ভুলবেন না:
এমনকি আপনার একই কলামগুলিতে বিভিন্ন সমাহার সহ একাধিক সূচীও থাকতে পারে - আপনার যদি অন্য কোয়েরিতে অন্য (বা ডিফল্ট) কোলেশন অনুসারে বাছাই করা পণ্যগুলিরও প্রয়োজন হয়।
নিয়মমাফিক করা
অপ্রয়োজনীয় স্ট্রিং (ভাল নাম) আপনার টেবিলগুলি এবং সূচিগুলিও সবিস্তারে ফুটিয়ে তোলে যা সবকিছুকে আরও ধীর করে তোলে। সঠিক টেবিল বিন্যাসের সাহায্যে আপনি বেশিরভাগ সমস্যা শুরু করতে পারেন could এই মত দেখতে পারে:
CREATE TABLE good (
good_id serial PRIMARY KEY
, good text NOT NULL
);
CREATE TABLE inventory (
good_id int REFERENCES good (good_id)
, the_date date NOT NULL
, quantity int NOT NULL
, PRIMARY KEY(good_id, the_date)
);
CREATE TABLE price (
good_id int REFERENCES good (good_id)
, the_date date NOT NULL
, price numeric NOT NULL
, PRIMARY KEY(good_id, the_date));
প্রাথমিক কীগুলি আমাদের প্রয়োজনীয় সমস্ত সূচক স্বয়ংক্রিয়ভাবে সরবরাহ করে (প্রায়)।
অনুপস্থিত বিবরণ উপর নির্ভর করে, একটি multicolumn সূচক উপর price
দ্বিতীয় কলামে এ আদেশ সাজানো পারফরম্যান্সের উন্নতি করতে পারে:
CREATE INDEX price_good_date_desc_idx ON price(good, the_date DESC);
আবার কোলেশন অবশ্যই আপনার প্রশ্নের সাথে মেলে (উপরে দেখুন)।
পোস্টগ্রিস 9.2 বা তারপরে ইনডেক্স-কেবল স্ক্যানগুলির জন্য "কভারিং সূচকগুলি" আরও কিছুকে সহায়তা করতে পারে - বিশেষত যদি আপনার টেবিলগুলি অতিরিক্ত কলাম ধারণ করে, সারণিকে আচ্ছাদন সূচকের চেয়ে যথেষ্ট বড় করে তোলে।
এই ফলাফলগুলি আরও দ্রুত:
বিদ্যমান না
SELECT i.the_date, p.the_date AS pricing_date, g.good, i.quantity, p.price
FROM inventory i
JOIN good g USING (good_id)
LEFT JOIN price p ON p.good_id = i.good_id AND p.the_date <= i.the_date
AND NOT EXISTS (
SELECT 1 FROM price p1
WHERE p1.good_id = p.good_id
AND p1.the_date <= i.the_date
AND p1.the_date > p.the_date
);
ডিস্টিন্ট চালু
SELECT DISTINCT ON (i.the_date)
i.the_date, p.the_date AS pricing_date, g.good, i.quantity, p.price
FROM inventory i
JOIN good g USING (good_id)
LEFT JOIN price p ON p.good_id = i.good_id AND p.the_date <= i.the_date
ORDER BY i.the_date, p.the_date DESC;
এসকিউএল ফিডল।
দ্রুত সমাধান
যদি এখনও এটি পর্যাপ্ত দ্রুত না হয় তবে দ্রুত সমাধান হতে পারে।
পুনরাবৃত্তির সিটিই / JOIN LATERAL
/ পারস্পরিক সম্পর্কযুক্ত সাবকোয়ারি
বিশেষত ভাল প্রতি অনেক দাম সহ ডেটা বিতরণের জন্য :
বস্তুগত দর্শন
আপনার যদি এটি প্রায়শই এবং দ্রুত চালানোর প্রয়োজন হয় তবে আমি আপনাকে একটি বস্তুগত দৃষ্টিভঙ্গি তৈরি করার পরামর্শ দিচ্ছি। আমি মনে করি এটি নিরাপদ বলে মনে করি, অতীতের তারিখগুলির জন্য মূল্য এবং জায়গুলি খুব কমই পরিবর্তিত হয়। ফলাফল একবার গণনা করুন এবং বস্তুগত দর্শন হিসাবে একটি স্ন্যাপশট সংরক্ষণ করুন।
পোস্টগ্রিজ 9.3+ পদার্থযুক্ত দর্শনগুলির জন্য স্বয়ংক্রিয় সমর্থন করেছে। আপনি পুরানো সংস্করণগুলিতে সহজেই একটি প্রাথমিক সংস্করণটি প্রয়োগ করতে পারেন।