PostgreSQL
 sql >> डेटाबेस >  >> RDS >> PostgreSQL

PostgreSQL 11 में सूचकांक परिवर्तन का अवलोकन

अनुक्रमणिका का सही अनुप्रयोग प्रश्नों को तेजी से प्रज्वलित कर सकता है।

इंडेक्स तेजी से डेटा पेजों तक पहुंचने के लिए पॉइंटर्स का उपयोग करते हैं।

PostgreSQL 11 में इंडेक्स में बड़े बदलाव हुए, बहुत से बहुप्रतीक्षित पैच जारी किए गए हैं।

आइए इस रिलीज की कुछ बेहतरीन विशेषताओं पर एक नजर डालते हैं।

समानांतर बी-ट्री इंडेक्स बनाता है

PostgreSQL 11 ने समानांतर अनुक्रमणिका निर्माण को सक्षम करने के लिए एक बुनियादी ढांचा पैच पेश किया।

अभी के लिए इसका उपयोग केवल बी-ट्री इंडेक्स के साथ किया जा सकता है।

समानांतर बी-ट्री इंडेक्स बनाना समानांतर काम (या सीरियल बिल्ड) के बिना एक ही काम करने से दो से तीन गुना तेज है।

PostgreSQL 11 में समानांतर अनुक्रमणिका निर्माण डिफ़ॉल्ट रूप से चालू है।

दो महत्वपूर्ण पैरामीटर हैं:

  • max_parallel_workers - उन कर्मचारियों की अधिकतम संख्या सेट करता है जो सिस्टम समानांतर प्रश्नों के लिए समर्थन कर सकता है।
  • max_parallel_maintenance_workers - अधिकतम संख्या में कार्यकर्ता प्रक्रियाओं को नियंत्रित करता है जिनका उपयोग INDEX बनाने के लिए किया जा सकता है।

आइए इसे एक उदाहरण से देखें:

severalnines=# CREATE TABLE test_btree AS SELECT generate_series(1,100000000) AS id;
SELECT 100000000
severalnines=#  SET maintenance_work_mem = '1GB';
severalnines=# \timing
severalnines=#  CREATE INDEX q ON test_btree (id);
TIME: 25294.185 ms (00:25.294)

आइए इसे 8-तरफ़ा समानांतर कार्य के साथ आज़माएँ:

severalnines=# SET maintenance_work_mem = '2GB';
severalnines=# SET max_parallel_workers = 16;
severalnines=# SET max_parallel_maintenance_workers = 8;
severalnines=# \timing
severalnines=# CREATE INDEX q1 ON test_btree (id);
TIME: 11001.240 ms (00:11.001)

हम समानांतर कार्यकर्ता के साथ प्रदर्शन अंतर देख सकते हैं, केवल एक छोटे से बदलाव के साथ 60% से अधिक प्रदर्शन करने वाले। अधिक प्रदर्शन प्राप्त करने के लिए रखरखाव_वर्क_मेम को भी बढ़ाया जा सकता है।

ALTER तालिका समानांतर श्रमिकों को बढ़ाने में भी मदद करती है। मैक्स_पैरेलल_मेंटेनेंस_वर्कर्स के साथ समानांतर वर्कर्स को बढ़ाने के लिए सिंटैक्स के नीचे का उपयोग किया जा सकता है। यह लागत मॉडल को पूरी तरह से दरकिनार कर देता है।

ALTER TABLE test_btree SET (parallel_workers = 24);

युक्ति:प्रतिकूल क्वेरी योजना को रोकने के लिए अनुक्रमणिका निर्माण पूर्ण होने के बाद डिफ़ॉल्ट पर रीसेट करें।

CONCURRENTLY विकल्प के साथ CREATE INDEX विशेष प्रतिबंधों के बिना समानांतर बिल्ड का समर्थन करता है, केवल पहला टेबल स्कैन वास्तव में समानांतर में किया जाता है।

गहन प्रदर्शन परीक्षण यहां देखे जा सकते हैं।

Hash, Gist, और Gin Indexes के लिए Predicate Locking जोड़ें

PostgreSQL 11 को हैश इंडेक्स, जिन इंडेक्स और जिस्ट इंडेक्स के लिए प्रेडिकेट लॉक सपोर्ट के साथ शिप किया गया है। ये उन अनुक्रमणिकाओं के साथ SERIALIZABLE लेन-देन अलगाव को और अधिक कुशल बना देंगे।

लाभ:प्रेडिकेट लॉकिंग झूठी सकारात्मक की संख्या को कम करके क्रमिक अलगाव स्तर पर बेहतर प्रदर्शन प्रदान कर सकता है जिससे अनावश्यक क्रमांकन विफलता होती है।

PostgreSQL 10 में, लॉक रेंज संबंध है, लेकिन PostgreSQL 11 में लॉक केवल पेज के रूप में पाया जाता है।

आइए इसका परीक्षण करें।

severalnines=# CREATE TABLE sv_predicate_lock1(c1 INT, c2 VARCHAR(10)) ;
CREATE TABLE
severalnines=# CREATE INDEX idx1_sv_predicate_lock1 ON sv_predicate_lock1 USING 'hash(c1) ;
CREATE INDEX
severalnines=# INSERT INTO sv_predicate_lock1 VALUES (generate_series(1, 100000),  'puja') ;
INSERT 0 100000
severalnines=#  BEGIN ISOLATION LEVEL SERIALIZABLE ;
BEGIN
severalnines=# SELECT * FROM sv_predicate_lock1 WHERE c1=10000 FOR UPDATE ;
  c1   |  c2
-------+-------
 10000 | puja
(1 row)

जैसा कि हम नीचे देख सकते हैं, ताला संबंध के बजाय पृष्ठ स्तर पर है। PostgreSQL 10 में यह संबंध स्तर पर था, इसलिए PostgreSQL 11 में समवर्ती लेनदेन के लिए यह एक बड़ी जीत है।

severalnines=# SELECT locktype, relation::regclass, mode FROM pg_locks ;
   locktype    |        relation         |      mode
---------------+-------------------------+-----------------
 relation      | pg_locks                | AccessShareLock
 relation      | idx1_sv_predicate_lock1 | AccessShareLock
 relation      | sv_predicate_lock1      | RowShareLock
 virtualxid    |                         | ExclusiveLock
 transactionid |                         | ExclusiveLock
 page          | idx1_sv_predicate_lock1 | SIReadLock
 tuple         | sv_predicate_lock1      | SIReadLock
(7 rows)

युक्ति:अनुक्रमिक स्कैन के लिए हमेशा संबंध-स्तर विधेय लॉक की आवश्यकता होगी। इसके परिणामस्वरूप क्रमिकरण विफलताओं की बढ़ी हुई दर हो सकती है। यह random_page_cost को कम करके और/या cpu_tuple_cost को बढ़ाकर इंडेक्स स्कैन के उपयोग को प्रोत्साहित करने में मददगार हो सकता है।

कुछ एक्सप्रेशन इंडेक्स के लिए HOT अपडेट की अनुमति दें

हीप ओनली टुपल (HOT) फीचर, अनावश्यक इंडेक्स प्रविष्टियों को समाप्त करता है और टेबल-वाइड वैक्यूम को निष्पादित किए बिना DELETEd या अप्रचलित अद्यतन टुपल्स द्वारा लिए गए स्थान के पुन:उपयोग की अनुमति देता है। यह समान-कुंजी वाली अनुक्रमणिका प्रविष्टियों के निर्माण से बचकर अनुक्रमणिका के आकार को कम करता है।

अगर अपडेट के बाद इंडेक्स एक्सप्रेशन का मान अपरिवर्तित रहता है, तो उन मामलों में महत्वपूर्ण प्रदर्शन को बढ़ावा देते हुए, जहां पहले PostgreSQL ने उन्हें अस्वीकार कर दिया था, वहां HOT अपडेट की अनुमति दें।

यह JSON->>फ़ील्ड जैसे इंडेक्स के लिए विशेष रूप से उपयोगी है जहां JSON मान बदलता है लेकिन अनुक्रमित मान नहीं होता है।

प्रदर्शन में गिरावट के कारण इस सुविधा को 11.1 में वापस ले लिया गया था (केवल साइमन के अनुसार एटी फ्री बीएसडी), अधिक विवरण / बेंचमार्क यहां पाया जा सकता है। इसे भविष्य की रिलीज़ में ठीक किया जाना चाहिए।

संपूर्ण हैश अनुक्रमणिका पृष्ठों को स्कैन करने की अनुमति दें

हैश इंडेक्स:क्वेरी प्लानर हैश इंडेक्स का उपयोग करने पर विचार करेगा जब भी एक अनुक्रमित कॉलम =ऑपरेटर का उपयोग करके तुलना में शामिल होता है। यह क्रैश सेफ भी नहीं था (वाल में लॉग इन नहीं) इसलिए इसे डीबी क्रैश के बाद फिर से बनाने की जरूरत है, और हैश में बदलाव स्ट्रीमिंग प्रतिकृति के माध्यम से नहीं लिखे गए थे।

PostgreSQL 10 में, हैश इंडेक्स WAL लॉग किया गया था, जिसका अर्थ है कि यह CRASH सुरक्षित है और इसे दोहराया जा सकता है। हैश इंडेक्स बी-ट्री की तुलना में बहुत कम जगह का उपयोग करते हैं ताकि वे मेमोरी में बेहतर तरीके से फिट हो सकें।

PostgreSQL 11 में, Btree इंडेक्स में "सिंगल पेज वैक्यूम" नामक एक ऑप्टिमाइज़ेशन होता है, जो इंडेक्स पेजों से डेड इंडेक्स पॉइंटर्स को अवसरवादी रूप से हटा देता है, जिससे बड़ी मात्रा में इंडेक्स ब्लोट को रोका जा सकता है, जो अन्यथा होता है। उसी तर्क को हैश इंडेक्स में पोर्ट किया गया है। यह अंतरिक्ष पुनर्चक्रण को तेज करता है, ब्लोट को कम करता है।

फ़ंक्शन इंडेक्स के आंकड़े

फ़ंक्शन इंडेक्स कॉलम के लिए सांख्यिकी मान निर्दिष्ट करना अब संभव है। यह एक विशेष अनुप्रयोग की दक्षता के लिए अत्यधिक मूल्यवान है। अब हम एक्सप्रेशन कॉलम पर आंकड़े एकत्र कर सकते हैं, जिससे योजनाकार को अधिक सटीक निर्णय लेने में मदद मिलेगी।

severalnines=# CREATE INDEX idx1_stats ON stat ((s1 + s2)) ;
CREATE INDEX
severalnines=# ALTER INDEX idx1_stats ALTER COLUMN 1 SET STATISTICS 1000 ;
ALTER INDEX
severalnines=# \d+ idx1_stats
 Index "public.idx1_stats"
Column | Type | Definition | Storage | Stats target
--------+---------+------------+---------+--------------
expr | numeric | (c1 + c2) | main | 1000
btree, for table "public.stat1"

एमचेक

एक नया Contrib मॉड्यूल amcheck जोड़ा गया है। केवल बी-ट्री इंडेक्स की जांच की जा सकती है।

आइए इसका परीक्षण करें!

severalnines=# CREATE EXTENSION amcheck ;
CREATE EXTENSION
severalnines=# SELECT bt_index_check('idx1_stats') ;
ERROR: invalid page in block 0 of relation base/16385/16580
severalnines=#CREATE INDEX idx1_hash_data1 ON data1 USING hash (c1) ;
CREATE INDEX
severalnines=# SELECT bt_index_check('idx1_hash_data1') ;
ERROR: only B-Tree indexes are supported as targets for verification
DETAIL: Relation "idx1_hash_data1" is not a B-Tree index.

स्थानीय विभाजन संभव है

PostgreSQL11 से पहले, चाइल्ड टेबल या पार्टीशन टेबल पर इंडेक्स बनाना संभव नहीं था।

PostgreSQL 11 में, जब CREATE INDEX को विभाजित टेबल / पैरेंट टेबल पर चलाया जाता है, तो यह विभाजित टेबल पर एक इंडेक्स के लिए कैटलॉग प्रविष्टियाँ बनाता है और मौजूदा विभाजन पर वास्तविक इंडेक्स बनाने के लिए कैस्केड करता है। यह उन्हें भविष्य के विभाजनों में भी बनाएगा।

आइए एक पैरेंट टेबल और उसका विभाजन बनाने का प्रयास करें:

severalnines=# create table test_part ( a int, list varchar(5) ) partition by list (list);
CREATE TABLE
severalnines=# create table part_1 partition of test_part for values in ('India');
CREATE TABLE
severalnines=# create table part_2 partition of test_part for values in ('USA');
CREATE TABLE
severalnines=#
severalnines=# \d+ test_part
                                        Table "public.test_part"
 Column |         Type         | Collation | Nullable | Default | Storage  | Stats target | Description
--------+----------------------+-----------+----------+---------+----------+--------------+-------------
 a      | integer              |           |          |         | plain    |              |
 list   | character varying(5) |           |          |         | extended |              |
Partition key: LIST (list)
Partitions: part_1 FOR VALUES IN ('India'),
            part_2 FOR VALUES IN ('USA')

आइए पैरेंट टेबल पर एक इंडेक्स बनाने की कोशिश करें:

severalnines=# create index i_test on test_part (a);
CREATE INDEX
severalnines=# \d part_2
                     Table "public.part_2"
 Column |         Type         | Collation | Nullable | Default
--------+----------------------+-----------+----------+---------
 a      | integer              |           |          |
 list   | character varying(5) |           |          |
Partition of: test_part FOR VALUES IN ('USA')
Indexes:
    "part_2_a_idx" btree (a)

severalnines=# \d part_1
                     Table "public.part_1"
 Column |         Type         | Collation | Nullable | Default
--------+----------------------+-----------+----------+---------
 a      | integer              |           |          |
 list   | character varying(5) |           |          |
Partition of: test_part FOR VALUES IN ('India')
Indexes:
    "part_1_a_idx" btree (a)

इंडेक्स को पोस्टग्रेएसक्यूएल 11 में सभी पार्टिशन में कैस्केड किया गया है, जो वास्तव में एक शानदार फीचर है।

कवरिंग इंडेक्स (इंडेक्स के लिए क्लॉज शामिल करें)

इंडेक्स में कॉलम जोड़ने के लिए एक INCLUDE क्लॉज निर्दिष्ट किया जा सकता है। यह उन स्तंभों को जोड़ते समय प्रभावी होता है जो किसी अद्वितीय अनुक्रमणिका के अनन्य अवरोध से संबंधित नहीं होते हैं। केवल-इंडेक्स स्कैन से अधिक प्रश्नों को लाभ देने की अनुमति देने के लिए INCLUDE कॉलम पूरी तरह से मौजूद है। अभी के लिए केवल बी-ट्री इंडेक्स INCLUDE क्लॉज का समर्थन करते हैं।

आइए बिना शामिल किए व्यवहार की जांच करें। यदि चयन में अतिरिक्त कॉलम दिखाई देते हैं तो यह केवल इंडेक्स स्कैन का उपयोग नहीं करेगा। इसे INCLUDE क्लॉज का उपयोग करके प्राप्त किया जा सकता है।

severalnines=# CREATE TABLE no_include (a int, b int, c int);
CREATE TABLE
severalnines=# INSERT INTO no_include SELECT 3 * val, 3 * val + 1, 3 * val + 2 FROM generate_series(0, 1000000) as val;
INSERT 0 1000001
severalnines=# CREATE UNIQUE INDEX old_unique_idx ON no_include(a, b);
CREATE INDEX
severalnines=# VACUUM ANALYZE;
VACUUM
EXPLAIN ANALYZE SELECT a, b FROM no_include WHERE a < 1000;  - It will do index only scan 
EXPLAIN ANALYZE SELECT a, b, c FROM no_include WHERE a < 1000; - It will not do index only scan as we have extra column in select. 
severalnines=# CREATE INDEX old_idx ON no_include (a, b, c);
CREATE INDEX
severalnines=# VACUUM ANALYZE;
VACUUM
severalnines=# EXPLAIN ANALYZE SELECT a, b, c FROM no_include WHERE a < 1000;   - It did index only scan as index on all three columns. 
                     QUERY PLAN
-------------------------------------------------
 Index Only Scan using old_idx on no_include
     (cost=0.42..14.92 rows=371 width=12)
     (actual time=0.086..0.291 rows=334 loops=1)
   Index Cond: (a < 1000)
   Heap Fetches: 0
 Planning Time: 2.108 ms
 Execution Time: 0.396 ms
(5 rows)

आइए शामिल क्लॉज के साथ प्रयास करें। नीचे दिए गए उदाहरण में UNIQUE CONSTRAINT कॉलम a और b में बनाया गया है, लेकिन इंडेक्स में c कॉलम शामिल है।

severalnines=# CREATE TABLE with_include (a int, b int, c int);
CREATE TABLE
severalnines=# INSERT INTO with_include SELECT 3 * val, 3 * val + 1, 3 * val + 2 FROM generate_series(0, 1000000) as val;
INSERT 0 1000001
severalnines=# CREATE UNIQUE INDEX new_unique_idx ON with_include(a, b) INCLUDE (c);
CREATE INDEX
severalnines=# VACUUM ANALYZE;
VACUUM
severalnines=#  EXPLAIN ANALYZE SELECT a, b, c FROM with_include WHERE a < 10000;
                       QUERY PLAN
-----------------------------------------------------
 Index Only Scan using new_unique_idx on with_include
     (cost=0.42..116.06 rows=3408 width=12)
     (actual time=0.085..2.348 rows=3334 loops=1)
   Index Cond: (a < 10000)
   Heap Fetches: 0
 Planning Time: 1.851 ms
 Execution Time: 2.840 ms
(5 rows)

मुख्य कॉलम सूची में कॉलम और शामिल सूची के कॉलम के बीच कोई ओवरलैप नहीं हो सकता है

severalnines=# CREATE UNIQUE INDEX new_unique_idx ON with_include(a, b) INCLUDE (a);
ERROR:  42P17: included columns must not intersect with key columns
LOCATION:  DefineIndex, indexcmds.c:373

मुख्य सूची में एक्सप्रेशन के साथ प्रयोग किया जाने वाला कॉलम काम करता है:

severalnines=# CREATE UNIQUE INDEX new_unique_idx_2 ON with_include(round(a), b) INCLUDE (a);
CREATE INDEX

अभिव्यक्तियों को शामिल सूची में उपयोग नहीं किया जा सकता क्योंकि उनका उपयोग केवल अनुक्रमणिका स्कैन में नहीं किया जा सकता है:

severalnines=# CREATE UNIQUE INDEX new_unique_idx_2 ON with_include(a, b) INCLUDE (round(c));
ERROR:  0A000: expressions are not supported in included columns
LOCATION:  ComputeIndexAttrs, indexcmds.c:1446

निष्कर्ष

पोस्टग्रेएसक्यूएल की नई विशेषताएं निश्चित रूप से डीबीए के जीवन में सुधार करेंगी, इसलिए यह ओपन सोर्स डीबी में एक मजबूत वैकल्पिक विकल्प बनने की ओर अग्रसर है। मैं समझता हूं कि इंडेक्स की कुछ विशेषताएं वर्तमान में बी-ट्री तक सीमित हैं, यह अभी भी PostgreSQL के लिए समानांतर निष्पादन युग की एक शानदार शुरुआत है और बारीकी से देखने के लिए एक अच्छे टूल की ओर बढ़ रहा है। धन्यवाद!


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. त्रुटि:वर्ण 46 . पर स्कीमा user1_gmail_com के लिए अनुमति अस्वीकृत

  2. बेंचमार्किंग पोस्टग्रेज-XL

  3. पोस्टग्रेज़ में, क्या आप टाइमस्टैम्प के लिए डिफ़ॉल्ट स्वरूपण सेट कर सकते हैं, सत्र या विश्व स्तर पर?

  4. एसक्यूएल - एकाधिक तालिकाओं से दृश्य बनाएं

  5. कुप्पी-SQLAlchemy लोअर केस इंडेक्स - कार्यात्मक लंघन, SQLAlchemy प्रतिबिंब द्वारा समर्थित नहीं है