পোস্টগ্রিসে আপনি একটি আইএন ধারাটি নির্দিষ্ট করতে পারেন:
SELECT * FROM user WHERE id IN (1000, 1001, 1002)
কেউ কী জানে যে আপনি সর্বাধিক সংখ্যক পরামিতি IN এ প্রবেশ করতে পারবেন?
পোস্টগ্রিসে আপনি একটি আইএন ধারাটি নির্দিষ্ট করতে পারেন:
SELECT * FROM user WHERE id IN (1000, 1001, 1002)
কেউ কী জানে যে আপনি সর্বাধিক সংখ্যক পরামিতি IN এ প্রবেশ করতে পারবেন?
উত্তর:
এখানে অবস্থিত উত্স কোড অনুসারে , লাইন 850 থেকে শুরু করে, পোস্টগ্র্যাসকিউএল স্পষ্টভাবে যুক্তির সংখ্যা সীমাবদ্ধ করে না।
নিম্নলিখিত 870 লাইন থেকে একটি কোড মন্তব্য:
/*
* We try to generate a ScalarArrayOpExpr from IN/NOT IN, but this is only
* possible if the inputs are all scalars (no RowExprs) and there is a
* suitable array type available. If not, we fall back to a boolean
* condition tree with multiple copies of the lefthand expression.
* Also, any IN-list items that contain Vars are handled as separate
* boolean conditions, because that gives the planner more scope for
* optimization on such clauses.
*
* First step: transform all the inputs, and detect whether any are
* RowExprs or contain Vars.
*/
এটি প্রকৃতপক্ষে বর্তমান প্রশ্নের উত্তর নয়, তবে এটি অন্যকেও সহায়তা করতে পারে।
অন্তত আমি বলতে পারি পোস্টগ্র্রেএসকিউএল জেডিবিসি ড্রাইভার 9.1 ব্যবহার করে পোস্টগ্র্রেএসকিউএল ব্যাকএন্ডে 32767 মান (= সংক্ষিপ্ত। MAX_VALUE) পাস করার যোগ্যতার প্রযুক্তিগত সীমা রয়েছে।
এটি পোস্টগ্রেএসকিএল জেডিবিসি ড্রাইভার সহ "এক্স থেকে মুছে যাওয়া আইডি যেখানে (... 100 ক মান ...)" পরীক্ষা করে:
Caused by: java.io.IOException: Tried to send an out-of-range integer as a 2-byte value: 100000
at org.postgresql.core.PGStream.SendInteger2(PGStream.java:201)
explain select * from test where id in (values (1), (2));
Seq Scan on test (cost=0.00..1.38 rows=2 width=208)
Filter: (id = ANY ('{1,2}'::bigint[]))
তবে যদি ২ য় ক্যোয়ারী চেষ্টা করে দেখুন:
explain select * from test where id = any (values (1), (2));
Hash Semi Join (cost=0.05..1.45 rows=2 width=208)
Hash Cond: (test.id = "*VALUES*".column1)
-> Seq Scan on test (cost=0.00..1.30 rows=30 width=208)
-> Hash (cost=0.03..0.03 rows=2 width=4)
-> Values Scan on "*VALUES*" (cost=0.00..0.03 rows=2 width=4)
আমরা দেখতে পাচ্ছি যে পোস্টগ্রিসগুলি টেম্প টেবিল তৈরি করে এবং এর সাথে যোগ দেয়
আপনি আইএন ক্লজটিতে যে উপাদানগুলিতে যাচ্ছেন তার সংখ্যার কোনও সীমা নেই। যদি আরও উপাদান থাকে তবে এটি এটিকে অ্যারে হিসাবে বিবেচনা করবে এবং তারপরে ডাটাবেসে প্রতিটি স্ক্যানের জন্য এটি অ্যারেতে রয়েছে কিনা তা খতিয়ে দেখবে। এই পদ্ধতির তেমন স্কেলযোগ্য নয়। আইএন ক্লজটি ব্যবহার না করে টেম্প টেবিলের সাহায্যে অভ্যন্তরীণ যোগদানের চেষ্টা করুন। পড়ুন http://www.xaprb.com/blog/2006/06/28/why-large-in-clauses-are-problematic/ আরও তথ্যের জন্য। INNER JOIN স্কেলগুলি পাশাপাশি কোয়েরি অপ্টিমাইজার ব্যবহার করা হ্যাশ জয়েন এবং অন্যান্য অপ্টিমাইজেশানের ব্যবহার করতে পারে। যদিও আইএন ক্লজ সহ অপ্টিমাইজারের জন্য ক্যোয়ারী অনুকূলিতকরণের কোনও উপায় নেই। এই পরিবর্তনটির সাথে আমি কমপক্ষে 2x এর গতিবেগ লক্ষ্য করেছি।
ORএবং INক্লোসগুলি ব্যবহার করে একটি বিস্তৃত কর্মক্ষমতা বাড়িয়ে তোলে, আমি পোস্টগ্রিস 9.5 এর সাথে সমস্যাটি নিশ্চিত করতে পারিনি, এই উত্তরটি দেখুন ।
ওরাকল ডিবি-র সাথে আরও অভিজ্ঞ হওয়ার কারণে আমিও এই সীমা সম্পর্কে উদ্বিগ্ন ছিলাম। আমি একটি তালিকায় '10'000 পরামিতি সহ একটি ক্যোয়ারির জন্য পারফরম্যান্স টেস্ট চালিয়েছি IN, প্রথম 100'000 পূর্ণসংখ্যার সাথে একটি টেবিল থেকে 100'000 অবধি প্রাথমিক সংখ্যাগুলি আনয়ন করেছি আসলে সমস্ত মৌলিক সংখ্যাকে কোয়েরি প্যারামিটার হিসাবে তালিকাভুক্ত করে ।
আমার ফলাফলগুলি সূচিত করে যে আপনার ক্যোয়ারী প্ল্যান অপটিমাইজারকে ওভারলোডিং বা সূচি ব্যবহার ব্যতীত পরিকল্পনা পাওয়ার বিষয়ে চিন্তা করার দরকার নেই , কারণ এটি ক্যোয়ারিকে = ANY({...}::integer[])এমনভাবে ব্যবহারের রূপান্তর করবে যেখানে এটি প্রত্যাশার মতো সূচকগুলি লাভ করতে পারে:
-- prepare statement, runs instantaneous:
PREPARE hugeplan (integer, integer, integer, ...) AS
SELECT *
FROM primes
WHERE n IN ($1, $2, $3, ..., $9592);
-- fetch the prime numbers:
EXECUTE hugeplan(2, 3, 5, ..., 99991);
-- EXPLAIN ANALYZE output for the EXECUTE:
"Index Scan using n_idx on primes (cost=0.42..9750.77 rows=9592 width=5) (actual time=0.024..15.268 rows=9592 loops=1)"
" Index Cond: (n = ANY ('{2,3,5,7, (...)"
"Execution time: 16.063 ms"
-- setup, should you care:
CREATE TABLE public.primes
(
n integer NOT NULL,
prime boolean,
CONSTRAINT n_idx PRIMARY KEY (n)
)
WITH (
OIDS=FALSE
);
ALTER TABLE public.primes
OWNER TO postgres;
INSERT INTO public.primes
SELECT generate_series(1,100000);
যাইহোক, pgsql- হ্যাকার মেলিং তালিকার এই (বরং পুরানো) থ্রেডটি ইঙ্গিত দেয় যে এই জাতীয় অনুসন্ধানের পরিকল্পনা করার জন্য এখনও একটি অবহেলিত ব্যয় রয়েছে, তাই আমার কথাটি লবণের দানা দিয়ে নিন।
আপনার কাছে যদি কোয়েরি থাকে তবে:
SELECT * FROM user WHERE id IN (1, 2, 3, 4 -- and thousands of another keys)
আপনার কোয়েরিটি আবার লিখলে আপনি পারফরম্যান্স বাড়িয়ে দিতে পারেন:
SELECT * FROM user WHERE id = ANY(VALUES (1), (2), (3), (4) -- and thousands of another keys)
EXPLAINবলে যে এটি অভ্যন্তরীণভাবে আমার IN (...)হিসাবে আবার লিখছে ANY ('{...}'::integer[])।
সবেমাত্র চেষ্টা করে দেখেছি। উত্তরটি হল -> 2-বাইটের মান হিসাবে সীমার বাইরে পূর্ণসংখ্যা: 32768
আপনি আইডির একটি ইচ্ছামত দীর্ঘ তালিকা যোগ করার পরিবর্তে সেই ক্যোয়ারীটি রিফ্যাক্টর করার বিষয়টি বিবেচনা করতে পারেন ... আইডস যদি সত্যই আপনার উদাহরণের প্যাটার্নটি অনুসরণ করে তবে আপনি একটি ব্যাপ্তি ব্যবহার করতে পারেন:
SELECT * FROM user WHERE id >= minValue AND id <= maxValue;
অন্য বিকল্পটি একটি অভ্যন্তরীণ নির্বাচন যুক্ত করুন:
SELECT *
FROM user
WHERE id IN (
SELECT userId
FROM ForumThreads ft
WHERE ft.id = X
);