अद्यतन: SQLKiddle में 100K पंक्तियों (और 2 अलग-अलग मामलों में से एक, कुछ के साथ एक (25) अलग मूल्यों और दूसरे के साथ बहुत सारे (25K मान) के साथ सभी 5 प्रश्नों का परीक्षण किया ।
एक बहुत ही सरल क्वेरी का उपयोग करना होगा UNION DISTINCT
। मुझे लगता है कि अगर चार कॉलम में से प्रत्येक पर एक अलग सूचकांक है तो यह सबसे अधिक कुशल होगा। यह चार कॉलम में से प्रत्येक पर एक अलग सूचकांक के साथ कुशल होगा, अगर पोस्टग्रेज ने लूज़ इंडेक्स स्कैन ऑप्टिमाइज़ेशन को लागू किया था , जो यह नहीं है। तो यह क्वेरी कुशल नहीं होगी क्योंकि इसमें तालिका के 4 स्कैन की आवश्यकता होती है (और कोई इंडेक्स का उपयोग नहीं किया जाता है):
-- Query 1. (334 ms, 368ms)
SELECT a AS abcd FROM tablename
UNION -- means UNION DISTINCT
SELECT b FROM tablename
UNION
SELECT c FROM tablename
UNION
SELECT d FROM tablename ;
एक UNION ALL
और पहले और फिर उपयोग करने के लिए किया जाएगा DISTINCT
। इसके लिए 4 टेबल स्कैन (और इंडेक्स का कोई उपयोग नहीं) की आवश्यकता होगी। खराब दक्षता नहीं जब मान कुछ कम होते हैं, और अधिक मूल्यों के साथ मेरे (सबसे व्यापक) परीक्षण में सबसे तेज हो जाता है:
-- Query 2. (87 ms, 117 ms)
SELECT DISTINCT a AS abcd
FROM
( SELECT a FROM tablename
UNION ALL
SELECT b FROM tablename
UNION ALL
SELECT c FROM tablename
UNION ALL
SELECT d FROM tablename
) AS x ;
अन्य उत्तरों ने सरणी फ़ंक्शंस या LATERAL
सिंटैक्स का उपयोग करके अधिक विकल्प प्रदान किए हैं । जैक की क्वेरी ( 187 ms, 261 ms
) में उचित प्रदर्शन है लेकिन एंड्रीएम की क्वेरी अधिक कुशल ( 125 ms, 155 ms
) लगती है । वे दोनों तालिका का एक क्रमिक स्कैन करते हैं और किसी भी सूचकांक का उपयोग नहीं करते हैं।
वास्तव में जैक की क्वेरी के परिणाम ऊपर दिखाए गए (अगर हम हटाते हैं order by
) की तुलना में थोड़ा बेहतर हैं और 4 आंतरिक को हटाकर distinct
और केवल बाहरी एक को छोड़कर आगे सुधार किया जा सकता है ।
अंत में, अगर - और केवल अगर - 4 कॉलम के अलग-अलग मान अपेक्षाकृत कम हैं, तो आप WITH RECURSIVE
ऊपर दिए गए लूज़ इंडेक्स स्कैन पेज में वर्णित हैक / ऑप्टिमाइज़ेशन का उपयोग कर सकते हैं और सभी 4 इंडेक्स का उपयोग कर सकते हैं, उल्लेखनीय रूप से तेज़ परिणाम के साथ! एक ही 100K पंक्तियों और लगभग 25 अलग-अलग मानों के साथ 4 कॉलम में फैले (केवल 2 एमएस में रन!) का परीक्षण किया गया, जबकि 25K अलग-अलग मूल्यों के साथ यह 368 एमएस के साथ सबसे धीमा है:
-- Query 3. (2 ms, 368ms)
WITH RECURSIVE
da AS (
SELECT min(a) AS n FROM observations
UNION ALL
SELECT (SELECT min(a) FROM observations
WHERE a > s.n)
FROM da AS s WHERE s.n IS NOT NULL ),
db AS (
SELECT min(b) AS n FROM observations
UNION ALL
SELECT (SELECT min(b) FROM observations
WHERE b > s.n)
FROM db AS s WHERE s.n IS NOT NULL ),
dc AS (
SELECT min(c) AS n FROM observations
UNION ALL
SELECT (SELECT min(c) FROM observations
WHERE c > s.n)
FROM dc AS s WHERE s.n IS NOT NULL ),
dd AS (
SELECT min(d) AS n FROM observations
UNION ALL
SELECT (SELECT min(d) FROM observations
WHERE d > s.n)
FROM db AS s WHERE s.n IS NOT NULL )
SELECT n
FROM
( TABLE da UNION
TABLE db UNION
TABLE dc UNION
TABLE dd
) AS x
WHERE n IS NOT NULL ;
SQLfiddle
सारांशित करने के लिए, जब अलग-अलग मूल्य कुछ होते हैं, तो पुनरावर्ती क्वेरी पूर्ण विजेता होती है, जबकि बहुत सारे मान, मेरा दूसरा, जैक का (नीचे का उन्नत संस्करण) और एंड्रीएम के प्रश्नों का सबसे अच्छा प्रदर्शन होता है।
देर से जोड़, 1 क्वेरी पर एक भिन्नता जो अतिरिक्त अलग-अलग कार्यों के बावजूद, मूल 1 से बहुत बेहतर प्रदर्शन करती है और केवल 2 के मुकाबले थोड़ी खराब होती है:
-- Query 1b. (85 ms, 149 ms)
SELECT DISTINCT a AS n FROM observations
UNION
SELECT DISTINCT b FROM observations
UNION
SELECT DISTINCT c FROM observations
UNION
SELECT DISTINCT d FROM observations ;
और जैक में सुधार:
-- Query 4b. (104 ms, 128 ms)
select distinct unnest( array_agg(a)||
array_agg(b)||
array_agg(c)||
array_agg(d) )
from t ;
SELECT a FROM tablename UNION SELECT b FROM tablename UNION SELECT c FROM tablename UNION SELECT d FROM tablename ;
?