इस पोस्ट में उल्लिखित प्रश्नों के लिए त्वरित प्रदर्शन तुलना यहां दी गई है।
वर्तमान सेटअप :
तालिका core_message
10,904,283 पंक्तियाँ हैं और test_boats
. में 60,740 पंक्तियाँ हैं (या core_message
. में 60,740 विशिष्ट mmsi )।
और मैं PostgreSQL 11.5 का उपयोग कर रहा हूं
केवल-अनुक्रमणिका स्कैन का उपयोग कर क्वेरी:
1) DISTINCT ON
. का उपयोग करके :
SELECT DISTINCT ON (mmsi) mmsi
FROM core_message;
2) RECURSIVE
. का उपयोग करना LATERAL
के साथ :
WITH RECURSIVE cte AS (
(
SELECT mmsi
FROM core_message
ORDER BY mmsi
LIMIT 1
)
UNION ALL
SELECT m.*
FROM cte c
CROSS JOIN LATERAL (
SELECT mmsi
FROM core_message
WHERE mmsi > c.mmsi
ORDER BY mmsi
LIMIT 1
) m
)
TABLE cte;
3) LATERAL
. के साथ एक अतिरिक्त तालिका का उपयोग करना :
SELECT a.mmsi
FROM test_boats a
CROSS JOIN LATERAL(
SELECT b.time
FROM core_message b
WHERE a.mmsi = b.mmsi
ORDER BY b.time DESC
LIMIT 1
) b;
केवल-अनुक्रमणिका स्कैन का उपयोग न करने वाली क्वेरी:
4) DISTINCT ON
. का उपयोग करके mmsi,time DESC
. के साथ INDEX
:
SELECT DISTINCT ON (mmsi) *
FROM core_message
ORDER BY mmsi, time desc;
5) DISTINCT ON
. का उपयोग करके पिछड़े mmsi,time
. के साथ UNIQUE CONSTRAINT
:
SELECT DISTINCT ON (mmsi) *
FROM core_message
ORDER BY mmsi desc, time desc;
6) RECURSIVE
. का उपयोग करना LATERAL
के साथ और mmsi,time DESC
INDEX
:
WITH RECURSIVE cte AS (
(
SELECT *
FROM core_message
ORDER BY mmsi , time DESC
LIMIT 1
)
UNION ALL
SELECT m.*
FROM cte c
CROSS JOIN LATERAL (
SELECT *
FROM core_message
WHERE mmsi > c.mmsi
ORDER BY mmsi , time DESC
LIMIT 1
) m
)
TABLE cte;
7) RECURSIVE
. का उपयोग करके LATERAL
के साथ और पिछड़ा mmsi,time
UNIQUE CONSTRAINT
:
WITH RECURSIVE cte AS (
(
SELECT *
FROM core_message
ORDER BY mmsi DESC , time DESC
LIMIT 1
)
UNION ALL
SELECT m.*
FROM cte c
CROSS JOIN LATERAL (
SELECT *
FROM core_message
WHERE mmsi < c.mmsi
ORDER BY mmsi DESC , time DESC
LIMIT 1
) m
)
TABLE cte;
8) LATERAL
. के साथ एक अतिरिक्त तालिका का उपयोग करना :
SELECT b.*
FROM test_boats a
CROSS JOIN LATERAL(
SELECT b.*
FROM core_message b
WHERE a.mmsi = b.mmsi
ORDER BY b.time DESC
LIMIT 1
) b;
अंतिम संदेश के लिए एक समर्पित तालिका का उपयोग करना:
9) यहाँ मेरा प्रारंभिक समाधान है, केवल अंतिम संदेश के साथ एक विशिष्ट तालिका का उपयोग करना। जैसे ही नए संदेश आते हैं, यह तालिका भर जाती है, लेकिन इसे इस तरह भी बनाया जा सकता है:
CREATE TABLE core_shipinfos AS (
WITH RECURSIVE cte AS (
(
SELECT *
FROM core_message
ORDER BY mmsi DESC , time DESC
LIMIT 1
)
UNION ALL
SELECT m.*
FROM cte c
CROSS JOIN LATERAL (
SELECT *
FROM core_message
WHERE mmsi < c.mmsi
ORDER BY mmsi DESC , time DESC
LIMIT 1
) m
)
TABLE cte);
फिर नवीनतम संदेश प्राप्त करने का अनुरोध उतना ही सरल है:
SELECT * FROM core_shipinfos;
परिणाम :
एकाधिक क्वेरी का औसत (तेज़ के लिए लगभग 5):
1) 9146 एमएस
2) 728 एमएस
3) 498 एमएस
4) 51488 एमएस
5) 54764 एमएस
6) 729 एमएस
7) 778 एमएस
8) 516 एमएस
9) 15 एमएस
निष्कर्ष:
मैं समर्पित टेबल समाधान पर टिप्पणी नहीं करूंगा, और इसे अंत तक रखूंगा।
अतिरिक्त तालिका (test_boats
) समाधान निश्चित रूप से यहां विजेता है लेकिन RECURSIVE
समाधान भी काफी कुशल है।
DISTINCT ON
. के प्रदर्शन में बहुत बड़ा अंतर है केवल-इंडेक्स स्कैन का उपयोग करना और जो इसका उपयोग नहीं कर रहा है, अन्य कुशल क्वेरी के लिए प्रदर्शन लाभ अपेक्षाकृत छोटा है।
यह समझ में आता है क्योंकि उन प्रश्नों में बड़ा सुधार यह तथ्य है कि उन्हें संपूर्ण core_message
पर लूप करने की आवश्यकता नहीं है तालिका लेकिन केवल अद्वितीय mmsi
. के सबसेट पर जो core_message
. की तुलना में काफ़ी छोटा (60K+) है टेबल का आकार (10M+)
एक अतिरिक्त नोट के रूप में, UNIQUE CONSTRAINT
का उपयोग करके क्वेरी के प्रदर्शन में कोई उल्लेखनीय सुधार नहीं दिखता है। अगर मैं mmsi,time DESC
. छोड़ दूं INDEX
. लेकिन उस अनुक्रमणिका को छोड़ने से निश्चित रूप से मुझे कुछ स्थान की बचत होगी (यह अनुक्रमणिका वर्तमान में 328MB लेती है)
समर्पित तालिका समाधान के बारे में:
प्रत्येक संदेश core_message
. में संग्रहीत होता है तालिका में स्थितिगत जानकारी (स्थिति, गति, शीर्षक, आदि) और जहाज की जानकारी (नाम, कॉलसाइन, आयाम, आदि), साथ ही जहाज पहचानकर्ता (एमएमएसआई) दोनों होते हैं।
मैं वास्तव में जो करने की कोशिश कर रहा हूं उस पर कुछ और पृष्ठभूमि देने के लिए:मैं जहाजों द्वारा उत्सर्जित संदेशों को AIS प्रोटोकॉल ।
जैसे, मुझे जो भी अनोखा एमएसआई मिला, वह मुझे इस प्रोटोकॉल के माध्यम से मिला। यह पूर्व-निर्धारित सूची नहीं है। यह नए MMSI को तब तक जोड़ता रहता है जब तक मुझे AIS का उपयोग करके दुनिया के हर जहाज नहीं मिल जाते।
उस संदर्भ में, अंतिम संदेश के रूप में जहाज की जानकारी के साथ एक समर्पित तालिका समझ में आती है।
जैसा कि हमने RECURSIVE
. के साथ देखा है, मैं ऐसी तालिका का उपयोग करने से बच सकता हूं समाधान, लेकिन... एक समर्पित तालिका अभी भी इस RECURSIVE
. से 50x तेज है समाधान।
वह समर्पित तालिका वास्तव में test_boat
. के समान है तालिका, केवल mmsi
. से अधिक जानकारी के साथ खेत। वैसे भी, mmsi
. के साथ एक टेबल होना core_message
. की हर अंतिम जानकारी के साथ केवल फ़ील्ड या तालिका तालिका मेरे आवेदन में समान जटिलता जोड़ें।
अंत में, मुझे लगता है कि मैं इस समर्पित तालिका के लिए जाऊंगा। यह मुझे अपराजेय गति प्रदान करेगा और मेरे पास अभी भी LATERAL
का उपयोग करने की संभावना होगी core_message
. पर ट्रिक , जो मुझे और अधिक लचीलापन देगा।