लंबे समय तक, PostgreSQL की सबसे ज्ञात कमियों में से एक प्रश्नों को समानांतर करने की क्षमता थी। संस्करण 9.6 के जारी होने के साथ, यह अब कोई समस्या नहीं होगी। इस विषय पर एक बहुत अच्छा काम किया गया है, प्रतिबद्ध 80558सी1 से शुरू होकर, समानांतर अनुक्रमिक स्कैन की शुरूआत, जिसे हम इस लेख के दौरान देखेंगे।
सबसे पहले, आपको ध्यान देना चाहिए:इस सुविधा का विकास निरंतर रहा है और कुछ मापदंडों ने एक प्रतिबद्ध और दूसरे के बीच नाम बदल दिए हैं। यह लेख 17 जून को लिए गए चेकआउट का उपयोग करते हुए लिखा गया है और यहां सचित्र कुछ विशेषताएं केवल 9.6 बीटा 2 संस्करण में मौजूद होंगी।
9.5 रिलीज की तुलना में, कॉन्फ़िगरेशन फ़ाइल के अंदर नए पैरामीटर पेश किए गए हैं। ये हैं:
- max_parallel_workers_per_gather :श्रमिकों की संख्या जो तालिका के क्रमिक स्कैन में सहायता कर सकते हैं;
- min_parallel_relation_size :न्यूनतम आकार जो योजनाकार के लिए अतिरिक्त श्रमिकों के उपयोग पर विचार करने के लिए होना चाहिए;
- समानांतर_सेटअप_लागत :योजनाकार पैरामीटर जो एक कार्यकर्ता को तत्काल करने की लागत का अनुमान लगाता है;
- समानांतर_टुपल_लागत :योजनाकार पैरामीटर जो एक कार्यकर्ता से दूसरे कर्मचारी को टपल स्थानांतरित करने की लागत का अनुमान लगाता है;
- force_parallel_mode :परीक्षण के लिए उपयोगी पैरामीटर, मजबूत समानता और एक प्रश्न जिसमें योजनाकार अन्य तरीकों से काम करेगा।
आइए देखें कि हमारे प्रश्नों को गति देने के लिए अतिरिक्त कर्मचारियों का उपयोग कैसे किया जा सकता है। हम एक INT फ़ील्ड और एक सौ मिलियन रिकॉर्ड के साथ एक परीक्षण तालिका बनाते हैं:
postgres=# CREATE TABLE test (i int);
CREATE TABLE
postgres=# INSERT INTO test SELECT generate_series(1,100000000);
INSERT 0 100000000
postgres=# ANALYSE test;
ANALYZE
PostgreSQL में max_parallel_workers_per_gather
है डिफ़ॉल्ट रूप से 2 पर सेट करें, जिसके लिए क्रमिक स्कैन के दौरान दो कर्मचारी सक्रिय हो जाएंगे।
एक साधारण अनुक्रमिक स्कैन कोई नवीनता प्रस्तुत नहीं करता है:
postgres=# EXPLAIN ANALYSE SELECT * FROM test;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------
Seq Scan on test (cost=0.00..1442478.32 rows=100000032 width=4) (actual time=0.081..21051.918 rows=100000000 loops=1)
Planning time: 0.077 ms
Execution time: 28055.993 ms
(3 rows)
वास्तव में, WHERE
. की उपस्थिति समानांतरीकरण के लिए खंड आवश्यक है:
postgres=# EXPLAIN ANALYZE SELECT * FROM test WHERE i=1;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------
Gather (cost=1000.00..964311.60 rows=1 width=4) (actual time=3.381..9799.942 rows=1 loops=1)
Workers Planned: 2
Workers Launched: 2
-> Parallel Seq Scan on test (cost=0.00..963311.50 rows=0 width=4) (actual time=6525.595..9791.066 rows=0 loops=3)
Filter: (i = 1)
Rows Removed by Filter: 33333333
Planning time: 0.130 ms
Execution time: 9804.484 ms
(8 rows)
हम पिछली कार्रवाई पर वापस जा सकते हैं और max_parallel_workers_per_gather
सेटिंग में अंतर देख सकते हैं 0 करने के लिए:
postgres=# SET max_parallel_workers_per_gather TO 0;
SET
postgres=# EXPLAIN ANALYZE SELECT * FROM test WHERE i=1;
QUERY PLAN
--------------------------------------------------------------------------------------------------------
Seq Scan on test (cost=0.00..1692478.40 rows=1 width=4) (actual time=0.123..25003.221 rows=1 loops=1)
Filter: (i = 1)
Rows Removed by Filter: 99999999
Planning time: 0.105 ms
Execution time: 25003.263 ms
(5 rows)
एक बार 2.5 गुना अधिक।
योजनाकार हमेशा समानांतर अनुक्रमिक स्कैन को सबसे अच्छा विकल्प नहीं मानता है। यदि कोई क्वेरी पर्याप्त रूप से चयनात्मक नहीं है और कार्यकर्ता से कार्यकर्ता में स्थानांतरित करने के लिए कई टुपल्स हैं, तो वह "क्लासिक" अनुक्रमिक स्कैन को प्राथमिकता दे सकता है:
postgres=# SET max_parallel_workers_per_gather TO 2;
SET
postgres=# EXPLAIN ANALYZE SELECT * FROM test WHERE i<90000000;
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------
Seq Scan on test (cost=0.00..1692478.40 rows=90116088 width=4) (actual time=0.073..31410.276 rows=89999999 loops=1)
Filter: (i < 90000000)
Rows Removed by Filter: 10000001
Planning time: 0.133 ms
Execution time: 37939.401 ms
(5 rows)
वास्तव में, यदि हम समानांतर अनुक्रमिक स्कैन को बलपूर्वक करने का प्रयास करते हैं, तो हमें एक खराब परिणाम मिलता है:
postgres=# SET parallel_tuple_cost TO 0;
SET
postgres=# EXPLAIN ANALYZE SELECT * FROM test WHERE i<90000000;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------
Gather (cost=1000.00..964311.50 rows=90116088 width=4) (actual time=0.454..75546.078 rows=89999999 loops=1)
Workers Planned: 2
Workers Launched: 2
-> Parallel Seq Scan on test (cost=0.00..1338795.20 rows=37548370 width=4) (actual time=0.088..20294.670 rows=30000000 loops=3)
Filter: (i < 90000000)
Rows Removed by Filter: 3333334
Planning time: 0.128 ms
Execution time: 83423.577 ms
(8 rows)
श्रमिकों की संख्या max_worker_processes
. तक बढ़ाई जा सकती है (डिफ़ॉल्ट:8)। हम parallel_tuple_cost
. का मान बहाल करते हैं और हम देखते हैं कि max_parallel_workers_per_gather
. को बढ़ाने से क्या होता है से 8.
postgres=# SET parallel_tuple_cost TO DEFAULT ;
SET
postgres=# SET max_parallel_workers_per_gather TO 8;
SET
postgres=# EXPLAIN ANALYZE SELECT * FROM test WHERE i=1;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------
Gather (cost=1000.00..651811.50 rows=1 width=4) (actual time=3.684..8248.307 rows=1 loops=1)
Workers Planned: 6
Workers Launched: 6
-> Parallel Seq Scan on test (cost=0.00..650811.40 rows=0 width=4) (actual time=7053.761..8231.174 rows=0 loops=7)
Filter: (i = 1)
Rows Removed by Filter: 14285714
Planning time: 0.124 ms
Execution time: 8250.461 ms
(8 rows)
भले ही PostgreSQL 8 कर्मचारियों तक का उपयोग कर सकता है, लेकिन इसने केवल छह को तत्काल किया है। ऐसा इसलिए है क्योंकि Postgres तालिका के आकार और min_parallel_relation_size
के अनुसार श्रमिकों की संख्या को भी अनुकूलित करता है। . पोस्टग्रेज द्वारा उपलब्ध कराए गए श्रमिकों की संख्या 3 के सामान्य अनुपात 3 और min_parallel_relation_size
के साथ एक ज्यामितीय प्रगति पर आधारित है। पैमाने कारक के रूप में। यहाँ एक उदाहरण है। 8MB डिफ़ॉल्ट पैरामीटर को ध्यान में रखते हुए:
Size | कार्यकर्ता |
---|---|
<8MB | 0 |
<24MB | 1 |
<72MB | 2 |
<216MB | 3 |
<648MB | 4 |
<1944MB | 5 |
<5822MB | 6 |
… | … |
हमारे टेबल का आकार 3458एमबी है, इसलिए 6 उपलब्ध कर्मचारियों की अधिकतम संख्या है।
postgres=# \dt+ test
List of relations
Schema | Name | Type | Owner | Size | Description
--------+------+-------+----------+---------+-------------
public | test | table | postgres | 3458 MB |
(1 row)
अंत में, मैं इस पैच के माध्यम से प्राप्त सुधारों का एक संक्षिप्त प्रदर्शन दूंगा। बढ़ती संख्या में श्रमिकों के साथ अपनी क्वेरी चलाने पर, हमें निम्नलिखित परिणाम प्राप्त होते हैं:
कार्यकर्ता | <वें संरेखण ="बाएं">समय|
---|---|
0 | 24767.848 ms |
1 | 14855.961 ms |
2 | 10415.661 ms |
3 | 8041.187 ms |
4 | 8090.855 ms |
5 | 8082.937 ms |
6 | 8061.939 ms |
हम देख सकते हैं कि जब तक आप प्रारंभिक मूल्य के एक तिहाई तक नहीं पहुंच जाते, तब तक समय में नाटकीय रूप से सुधार होता है। इस तथ्य की व्याख्या करना भी आसान है कि हम 3 और 6 श्रमिकों के उपयोग के बीच सुधार नहीं देखते हैं:जिस मशीन पर परीक्षण चलाया गया था उसमें 4 सीपीयू हैं, इसलिए मूल प्रक्रिया में 3 और श्रमिकों को जोड़ने के बाद परिणाम स्थिर हैं। ।
अंत में, PostgreSQL 9.6 ने क्वेरी समानांतरकरण के लिए चरण निर्धारित किया है, जिसमें समानांतर अनुक्रमिक स्कैन केवल पहला शानदार परिणाम है। हम यह भी देखेंगे कि 9.6 में, समेकन समानांतर हो गए हैं, लेकिन यह एक अन्य लेख के लिए जानकारी है जो आने वाले हफ्तों में जारी किया जाएगा!