Postgres में, आप इस तरह एक IN क्लॉज निर्दिष्ट कर सकते हैं:
SELECT * FROM user WHERE id IN (1000, 1001, 1002)
क्या किसी को पता है कि अधिकतम कितने पैरामीटर आप IN में पास कर सकते हैं?
Postgres में, आप इस तरह एक IN क्लॉज निर्दिष्ट कर सकते हैं:
SELECT * FROM user WHERE id IN (1000, 1001, 1002)
क्या किसी को पता है कि अधिकतम कितने पैरामीटर आप IN में पास कर सकते हैं?
जवाबों:
यहां स्थित स्रोत कोड के अनुसार , लाइन 850 पर शुरू होने के बाद, PostgreSQL स्पष्ट रूप से तर्कों की संख्या को सीमित नहीं करता है।
निम्नलिखित पंक्ति 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.
*/
यह वास्तव में वर्तमान प्रश्न का उत्तर नहीं है, हालांकि यह दूसरों की भी मदद कर सकता है।
कम से कम मैं बता सकता हूं कि पोस्ग्रेसक्यूएल के JDBC ड्राइवर 9.1 का उपयोग करते हुए, PostgreSQL बैकएंड के लिए 32767 मूल्यों (= Short.MAX_VALUE) की एक तकनीकी सीमा है।
यह postgresql jdcc ड्राइवर के साथ "x से डिलीट जहाँ आईडी (... 100k मान ...)" की एक परीक्षा है:
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)
हम देख सकते हैं कि पोस्टग्रुप टेम्प टेबल का निर्माण करते हैं और इसके साथ जुड़ते हैं
उन तत्वों की संख्या की कोई सीमा नहीं है जिन्हें आप IN क्लॉज में दे रहे हैं। यदि अधिक तत्व हैं, तो इसे सरणी के रूप में माना जाएगा और फिर डेटाबेस में प्रत्येक स्कैन के लिए यह जांच करेगा कि यह सरणी में निहित है या नहीं। यह दृष्टिकोण इतना स्केलेबल नहीं है। इनवॉइस का उपयोग करने के बजाय अस्थायी तालिका के साथ INNER JOIN का उपयोग करने का प्रयास करें। अधिक जानकारी के लिए http://www.xaprb.com/blog/2006/06/28/why-large-in-clauses-are-problematic/ देखें । INNER JOIN तराजू के साथ-साथ क्वेरी ऑप्टिमाइज़र का उपयोग करके हैश ज्वाइन और अन्य ऑप्टिमाइज़ेशन का उपयोग किया जा सकता है। जबकि IN खंड के साथ ऑप्टिमाइज़र के लिए क्वेरी को ऑप्टिमाइज़ करने का कोई तरीका नहीं है। मैंने इस बदलाव के साथ कम से कम 2x का स्पीडअप देखा है।
OR
और IN
पार्स करने और इस तरह के प्रश्नों की योजना बनाने में बड़ा भूमि के ऊपर के कारण खंड, मैं Postgres 9.5 के साथ समस्या यह पुष्टि नहीं कर सके, को देखने के इस जवाब ।
जैसा कि ओरेकल डीबी के साथ कोई और अनुभव करता है, मैं इस सीमा के बारे में भी चिंतित था। मैंने एक- IN
सूची में ~ 10'000 मापदंडों के साथ क्वेरी के लिए एक प्रदर्शन परीक्षण किया , जिसमें प्राइमरी नंबर को क्वेरी पैरामीटर्स के रूप में सभी प्रमुख नंबरों को सूचीबद्ध करके पहले 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[])
।
आप मनमाने ढंग से आईडी की लंबी सूची जोड़ने के बजाय उस क्वेरी को फिर से भरने पर विचार कर सकते हैं ... यदि आप वास्तव में अपने उदाहरण में पैटर्न का पालन करते हैं तो आप एक सीमा का उपयोग कर सकते हैं:
SELECT * FROM user WHERE id >= minValue AND id <= maxValue;
एक अन्य विकल्प एक आंतरिक चयन जोड़ने के लिए है:
SELECT *
FROM user
WHERE id IN (
SELECT userId
FROM ForumThreads ft
WHERE ft.id = X
);