PostgreSQL 17: צעד גדול קדימה בביצועים, שכפול לוגי ויותר

לאחר בטא 3 מוצלחת באוגוסט 2024, קבוצת הפיתוח של PostgreSQL שחררה את גרסת ה-GA ב-26 בספטמבר. לאחרונה, כתבתי בבלוג על כמה מתכונות השכפול הלוגי המרכזיות שתראו ב-PostgreSQL 17. בבלוג זה, אתאר כמה תכונות ביצועים חדשות שתמצאו ב-Postgres 17 וכן תכונת שכפול לוגי חשובה נוספת שלא כיסיתי בבלוג הקודם שלי בסדרה זו.

PostgreSQL צמח באופן מרשים לאורך השנים, ועם כל גרסה עיקרית, הוא הפך למסד נתונים יותר חזק, אמין ומגיב עבור יישומים ארגוניים קריטיים ולא קריטיים. הקהילה הגלובלית והתוססת של PostgreSQL תורמת להצלחתו של PostgreSQL, ומקפידה לבחון ולסקור בקפידה את כל השינויים לפני הוספתם לקוד המקור של הפרויקט. מעודד גם לראות שמות טכנולוגיים גדולים כמו מיקרוסופט, גוגל, אפל ואחרים משקיעים ב-Postgres על ידי פיתוח מומחיות פנימית ותרומה לקהילת הקוד הפתוח.

שיפורים בשכפול לוגי סוללים את הדרך להוספת תמיכה ב-PostgreSQL מבוזר לפונקציונליות הליבה. PostgreSQL מבוזר מתייחס ליישום של PostgreSQL בארכיטקטורה מבוזרת, המאפשרת יכולת הרחבה משופרת, עמידות בפני תקלות וביצועים משופרים על פני מספר צמתים.

עכשיו, ללא עיכוב נוסף, בואו נדון בכמה תכונות ביצועים של PostgreSQL 17.

ביצועי שאילתות משופרים עם CTEs ממומשים

תבניות המסגרת המשותפת (CTEs) בPostgreSQL הן מערכות תוצאה זמניות שניתן להשתמש בהן בתוך הצעה SELECT, INSERT, UPDATE או DELETE. הן מעלות את קריאת המשפטים ואת ארגון השאלות המורכבות ויכולות להיות משנות, מה שעושה אותן מאוד שימושיות במידע היררכי. הסינTAX הבסיסי של בקשת הCTE הוא בדיוק כך:

 

WITH cte_names AS  
(– QUERY here ) 
Select * from cte_names;

הוסף המילה WITH בתוך בקשת כדי ליצור את הCTE; הבקשה הורכבת (שמגדירה את התוצאה) מבואה אחרי הפרישה AS אחרי שמו הCTE. אחרי הגדירה של הCTE, ניתן להתייחס לה באופן מקביל לשם מידע של הCTE ולבצע פעולות נוספות על התוצאה בתוך אותה בקשה.

PostgreSQL 17 ממשיך לשפר את הביצועים והיכולות הקשורים בCTEs, כולל שיפורים בתכנון הבקשות ובביצוען. גרסאות ישנות של Postgres מטפלות בCTEs כגדרות עיצוב, אז המתכנן לא יכול להדביק את הדיקטים לתחתיתן. אך מאז PostgreSQL 12 ומעלה, ניתן להגדיר את התכניות הביצועים היעילות יותר. תמיד עליך לנתח את הבקשות שלך ולשקול את התכניות הביצועים בזמן שהביצועים הם קריטיים.

מידע על ביצועים: אם תשתמש באותו קבוצת תוצאות מספר פעמים, יצירו מבנה זרימת מידע (CTE) בעזרת מילים מסוימות MATERIALIZED. כשאתה יוצר מבנה זרימת מידע ממומן, Postgres מחשב ומאחסן את תוצאות שאלת ההוראה הורידה. אז, שאלות באחריות לא צריכות לבצע חישובים מורכבים פעמיות רבות אם אתה מזהה את הCTE במספר פעמים.

הוספת נתונים על מבנה זרימת מידע ממומן, Postgres 17 משפרת את הCTE הממומנים

בעיקר, מבנה זרימת מידע ממומן מתפקד כגדר שיפור, שאומר שהשאלה החיצונית לא תשפיע על הארגון של השאלה התת חיצונית אחרי שהארגון נבחר. לשאלה החיצונית יש גישה לרוחב המצפה ולמספר השורות של תוצאת הCTE, אז זה הגיוני להעביר את הנתונים על העמודות מהשאלה התת חיצונית לארגון השאלה החיצונית. השאלה החיצונית יכולה להשתמש במידע הזה כך שנתונים על מבנה העמודות יתפצצו לעמודה החיצונית אבל לא לתוך ארגון הCTE.

הבugs הזה הודבק לקהילה כולל מקטע בדיקה פשוט שימושי להדגמת השיפור וההשפעה על ארגון השאלות בגלל השיפור הזה.

מדגם: השוואה בין התנהגות Postgres 16 לPostgres 17

ראשית, אנחנו יוצרים את החלל העבודה שלנו בPostgres 16 ומבצעים בו ANALYZE בעזרת ערימות של

 

postgres=# create table t1(a int);
CREATE TABLE
postgres=# create table t2(b int);
CREATE TABLE
postgres=# create index my_index on t1 using btree (a);
CREATE INDEX
postgres=# insert into t1 select generate_series(1, 100000) from generate_series(1, 3);
INSERT 0 300000
postgres=# insert into t2 select generate_series(1, 100) from generate_series(1, 10);
INSERT 0 1000
postgres=# analyze t1;
ANALYZE
postgres=# analyze t2;
ANALYZE

Then, we create our materialized CTE:

postgres=# explain analyze with my_cte as materialized (select b from t2) select *
from t1 where t1.a in (select b from my_cte);

The query plan from our Postgres 16 code sample contains:

QUERY PLAN         
----------------------------------------------------------------------
 Nested Loop  (cost=37.92..856.50 rows=2966 width=4) (actual time=0.574..0.722 rows=300 loops=1)
   CTE my_cte
     ->  Seq Scan on t2  (cost=0.00..15.00 rows=1000 width=4) (actual time=0.038..0.161 rows=1000 loops=1)
   ->  HashAggregate  (cost=22.50..24.50 rows=200 width=4) (actual time=0.449..0.461 rows=100 loops=1)
         Group Key: my_cte.b
         Batches: 1  Memory Usage: 40kB
         ->  CTE Scan on my_cte  (cost=0.00..20.00 rows=1000 width=4) (actual time=0.046..0.322 rows=1000 loops=1)
   ->  Index Only Scan using my_index on t1  (cost=0.42..4.06 rows=3 width=4) (actual time=0.002..0.002 rows=3 loops=1
00)
         Index Cond: (a = my_cte.b)
         Heap Fetches: 0
 Planning Time: 1.242 ms
 Execution Time: 1.051 ms
(12 rows)

כפי שאתה יכול לראות בתוכנית השאלה, הנתונים העלובים של 200 שורות מהשאלה התת-מידע הם שגויים, וזה משפיע על התוכנית הכללית.

 

   ->  HashAggregate  (cost=22.50..24.50 rows=200 width=4) (actual time=0.449..0.461 rows=100 loops=1)
         Group Key: my_cte.b

אחר כך, אנחנו בדיקנו את אותה ההגדרה והשאלה בפוסטגרס 17:

 

postgres=# explain analyze with my_cte as materialized (select b from t2) select *
from t1 where t1.a in (select b from my_cte);
                                                            QUERY PLAN                           
                                 
-------------------------------------------------------------------------------------------------
---------------------------------
 Merge Join  (cost=42.25..54.29 rows=302 width=4) (actual time=0.627..0.712 rows=300 loops=1)
   Merge Cond: (t1.a = my_cte.b)
   CTE my_cte
     ->  Seq Scan on t2  (cost=0.00..15.00 rows=1000 width=4) (actual time=0.031..0.134 rows=1000
 loops=1)
   ->  Index Only Scan using my_index on t1  (cost=0.42..7800.42 rows=300000 width=4) (actual tim
e=0.027..0.049 rows=301 loops=1)
         Heap Fetches: 0
   ->  Sort  (cost=26.82..27.07 rows=100 width=4) (actual time=0.598..0.604 rows=100 loops=1)
         Sort Key: my_cte.b
         Sort Method: quicksort  Memory: 25kB
         ->  HashAggregate  (cost=22.50..23.50 rows=100 width=4) (actual time=0.484..0.494 rows=1
00 loops=1)
               Group Key: my_cte.b
               Batches: 1  Memory Usage: 24kB
               ->  CTE Scan on my_cte  (cost=0.00..20.00 rows=1000 width=4) (actual time=0.033..0
.324 rows=1000 loops=1)
 Planning Time: 1.066 ms
 Execution Time: 0.946 ms
(15 rows)

כפי שאתה יכול לראות בתוכנית השאלה של פוסטגרס 17, הנתונים העלובים מהשאלה התת-מידע מתעברים באופן נכון למתכנן העל של השאלה החיצונית. זה עוזר לפוסטגרס 17 לבחור תוכנית טובה יותר ששיעזר להארגן את זמני הביצוע של השאלה.

זו שאלה פשוטה, אך עם שאלות גדולות ומורכבות יותר, השינוי הזה יכול להיות מקור להבדלים ביצועיים גדולים.

עברת מפת-דרכים משאלה תת-מידע לשאלה חיצונית

עוד שיפור מעניין בפעולות התת-מידע בפוסטגרס 17 הוא העברת מפת-דרכים מהשאלה תת-מידע לשאלה חיצונית. בפוסטגרס, מפת-דרכים הם חלק מתהליך התכנון הביצועי שמשמש בעיקר למיון ולסדרה בשאלות הדורשות מיון מורכב, כמו שאלות עם פסולת ORDER BY, או כשצריך לסדר למטרות אחרות כמו התאחדות שילובים.

לפני פוסטגרס 17, סדר השיחים של השאלה התת-מידע המוסיפת לא נשירה לשאלה החיצונית, אפילו אם הסדר הוגן על ידי נקודת הסריקה המוסיפה או נקודת הסדר. חסרון סדר הוגן מאפשר למתכנן

עם PostgreSQL 17, אם עכשיו ערך מסויים ב CTE מורכב ויש לו סדר מיון ספציפי, מתכנן יכול להשתמש במידע הזה בשאילת השאילת השורה החיצונית, שישפר את הביצועים על ידי הדמיית סדרים מחזרים או אפשר שימוש בשילובים יעילים יותר. כפי שהוערך בתגובות ההגשה על ידי Tom Lane:

"הקוד לעילוי מסלולים הדרך לתוך שאילת השאילה החיצונית קיים כבר עבור שאילות תת שאילה רגילות RTE_SUBQUERY, אבל הוא לא נעשה בשימוש עבור CTEs, אולי מפני דאגה לשמירה על גדר האופטימיזציה בין ה CTE לשאילת השאילה החיצונית."

שינוי פשוט זה בקוד המקור של Postgres צריך להסיע שיפורים בביצועים עבור שאילות שעשויות להכיל ערכים מורכבים ב CTEs, בעיקר אלה בהם יכולים להיות מועדבים סדרים או שילובים מתאימים לסדר המיוני של התוצאות של ה CTE.

הנה דוגמא בשימוש במידע בביצועי הבדיקה של PostgreSQL regression:

 

postgres=# CREATE TABLE tenk1 (
postgres(#         unique1         int4,
postgres(#         unique2         int4,
postgres(#         two                     int4,
postgres(#         four            int4,
postgres(#         ten                     int4,
postgres(#         twenty          int4,
postgres(#         hundred         int4,
postgres(#         thousand        int4,
postgres(#         twothousand     int4,
postgres(#         fivethous       int4,
postgres(#         tenthous        int4,
postgres(#         odd                     int4,
postgres(#         even            int4,
postgres(#         stringu1        name,
postgres(#         stringu2        name,
postgres(#         string4         name
postgres(# );
CREATE TABLE
postgres=# CREATE INDEX tenk1_unique1 ON tenk1 USING btree(unique1 int4_ops);
CREATE INDEX
postgres=# \copy tenk1 FROM '~/projects/postgres/src/test/regress/data/tenk.data';
COPY 10000
postgres=# VACUUM ANALYZE tenk1;
VACUUM

התוכנית הבדיקה מקטע שלנו מבוסס על ביצועי הבדיקה של Postgres 16 מכילה את הבאות:

 

postgres=# explain analyze with x as materialized (select unique1 from tenk1 b order by unique1)
select count(*) from tenk1 a
  where unique1 in (select * from x);
                                                                  QUERY PLAN                                                               
   
-------------------------------------------------------------------------------------------------------------------------------------------
---
 Aggregate  (cost=764.29..764.30 rows=1 width=8) (actual time=21.592..21.593 rows=1 loops=1)
   CTE x
     ->  Index Only Scan using tenk1_unique1 on tenk1 b  (cost=0.29..306.29 rows=10000 width=4) (actual time=0.046..1.415 rows=10000 loops=
1)
           Heap Fetches: 0
   ->  Nested Loop  (cost=225.28..445.50 rows=5000 width=0) (actual time=7.545..20.911 rows=10000 loops=1)
         ->  HashAggregate  (cost=225.00..227.00 rows=200 width=4) (actual time=7.535..9.051 rows=10000 loops=1)
               Group Key: x.unique1
               Batches: 1  Memory Usage: 929kB
               ->  CTE Scan on x  (cost=0.00..200.00 rows=10000 width=4) (actual time=0.070..3.933 rows=10000 loops=1)
         ->  Index Only Scan using tenk1_unique1 on tenk1 a  (cost=0.29..1.08 rows=1 width=4) (actual time=0.001..0.001 rows=1 loops=10000)
               Index Cond: (unique1 = x.unique1)
               Heap Fetches: 0
 Planning Time: 0.806 ms
 Execution Time: 21.890 ms
(14 rows)

התוכנית הבדיקה מקטע שלנו מבוסס על ביצוגי הבדיקה של Postgres 17 מכילה את הבאות:

 

postgres=# explain analyze with x as materialized (select unique1 from tenk1 b order by unique1)
select count(*) from tenk1 a
  where unique1 in (select * from x);
                                                                    
QUERY PLAN                                                                    
------------------------------------------------------------------------------------------------------------------------------- Aggregate  (cost=987.55..987.56 rows=1 width=8) (actual time=8.777..8.778 rows=1 loops=1)
   CTE x
     ->  Index Only Scan using tenk1_unique1 on tenk1 b  (cost=0.29..306.29 rows=10000 width=4) (actual time=0.010..1.095 rows=100
00 loops=1)
           Heap Fetches: 0
   ->  Merge Semi Join  (cost=0.31..656.26 rows=10000 width=0) (actual time=0.037..8.024 rows=10000 loops=1)
         Merge Cond: (a.unique1 = x.unique1)
         ->  Index Only Scan using tenk1_unique1 on tenk1 a  (cost=0.29..306.29 rows=10000 width=4) (actual time=0.013..1.262 rows
=10000 loops=1)
               Heap Fetches: 0
         ->  CTE Scan on x  (cost=0.00..200.00 rows=10000 width=4) (actual time=0.016..3.678 rows=10000 loops=1)
 Planning Time: 0.800 ms
 Execution Time: 8.899 ms
(11 rows)

בפוסטגרס 16 ובפוסטגרס 17, התוכניות החיפוש מאוד שונות בגלל השיפור בגרסה 17 הזו. זו דוגמה קטנה; ניתן לראות שהרווח הביצועי יהיה משמעותי בשאילות גדולות יותר. שימו לב שהשיפור מועיל רק אם בחיפושית הקדמית יש ORDER BY clause.

סקנים בעלי B-Tree מהירים עבור מערך סקלרי

בפוסטgreSQL, ScalarArrayOpExpr הוא סוג של עץ נתונים בתוכנית הביצוע שמעבדה שאילות שעוברים סביב עיבודים כמו IN או ANY עם מערכות או רשימות של ערכים. הוא מועיל בעיקר לשאילות בהן אתה משווה עמודה בעודף על קבוצת ערכים, כמו SELECT * FROM table WHERE column = ANY(ARRAY[1, 2, 3]);.

ScalarArrayOpExpr מאפשר לפוסטgreSQL לאופיטים של שאילות שעוברים סביב הרבה השוואות שמשתמשות בIN או ANY. בפוסטgreSQL 17 ניעשה שיפורים חדשים בביצועים האלה כדי להאיץ אותם אפילו יותר.

בפוסטgreSQL 17, נעשו שיפורים משמעותיים בסקנים בעלי B-Tree, שמוטיעים ביצועים, בעיקר עבור שאילות עם רשימות IN גדולות או תנאים ANY. השיפורים האלה מורידים את מספר הסקנים המבצעות במערכת, כתוצאה מכך יותר מהמחשבה של הCPU ועמודות הטעם, וזה מוביל להיות יותר מהירה בביצוע שאילות.

אחד מהשיפורים המרכזיים הוא בטיפול בביטויי פעולות מערך סקלריים (SAOP), שמאפשר עיבוד יעיל יותר של אינדקסי B-tree, במיוחד עבור שאילתות רב-ממדיות. לדוגמה, כאשר יש לך מספר עמודות אינדקס (כל אחת עם רשימת IN משלה), PostgreSQL 17 יכול כעת לעבד את הפעולות האלה באופן יעיל יותר בסריקה אחת של אינדקס, במקום מספר סריקות כפי שהיה בגרסאות קודמות. זה יכול להוביל לשיפורי ביצועים של 20-30% בעומסים מוגבלי CPU בהם גישות לדפים היוו בעבר צוואר בקבוק.

בנוסף, PostgreSQL 17 מציג ניהול טוב יותר של נעילות פנימיות, ובכך משפר את הביצועים עבור עומסים בעלי תחרותיות גבוהה, במיוחד כאשר מבצעים סריקה של מספר ממדים בתוך אינדקס B-tree.

נוכל להדגים זאת בדוגמה פשוטה. נשתמש באותו טבלה tenk1 ונתונים שהשתמשנו בהם בדוגמה הקודמת מחבילת הרגרסיה של Postgres.

הדוגמה שלנו, רצה תחילה על Postgres 16:

 

CREATE TABLE tenk1 (
postgres(#         unique1         int4,
postgres(#         unique2         int4,
postgres(#         two                     int4,
postgres(#         four            int4,
postgres(#         ten                     int4,
postgres(#         twenty          int4,
postgres(#         hundred         int4,
postgres(#         thousand        int4,
postgres(#         twothousand     int4,
postgres(#         fivethous       int4,
postgres(#         tenthous        int4,
postgres(#         odd                     int4,
postgres(#         even            int4,
postgres(#         stringu1        name,
postgres(#         stringu2        name,
postgres(#         string4         name
postgres(# );
CREATE TABLE
postgres=# CREATE INDEX tenk1_unique1 ON tenk1 USING btree(unique1 int4_ops);
CREATE INDEX
postgres=# \copy tenk1 FROM '~/projects/postgres/src/test/regress/data/tenk.data';
COPY 10000
postgres=# EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM tenk1 WHERE unique1 IN (1, 2, 3);
                                                       QUERY PLAN                                                        
-------------------------------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on tenk1  (cost=14.20..330.12 rows=176 width=244) (actual time=0.138..0.153 rows=3 loops=1)
   Recheck Cond: (unique1 = ANY ('{1,2,3}'::integer[]))
   Heap Blocks: exact=3
   Buffers: shared hit=9
   ->  Bitmap Index Scan on tenk1_unique1  (cost=0.00..14.16 rows=176 width=0) (actual time=0.102..0.102 rows=3 loops=1)
         Index Cond: (unique1 = ANY ('{1,2,3}'::integer[]))
         Buffers: shared hit=6
 Planning:
   Buffers: shared hit=2
 Planning Time: 0.900 ms
 Execution Time: 0.242 ms
(11 rows)
postgres=# SELECT idx_scan, idx_tup_fetch FROM pg_stat_user_tables WHERE relname = 'tenk1';
 idx_scan | idx_tup_fetch 
----------+---------------
        3 |             3
(1 row)

בשאילתה הקודמת, ניתן לראות שהפגיעה בבאפר המשותף עבור השאילתה IN הייתה 9 ושלקח 3 סריקות אינדקס כדי לקבל את התוצאות מסריקת האינדקס. ב-PostgreSQL, המונח פגיעה משותפת מתייחס לסוג ספציפי של פגיעה במטמון הקשורה לניהול באפר. פגיעה משותפת מתרחשת כאשר PostgreSQL מגיש בלוק נתונים או דף מהבריכה המשותפת של הבאפר ולא מהדיסק, ובכך משפר את ביצועי השאילתה.

אותה דוגמה, הפעם רצה על Postgres 17:

 

EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM tenk1 WHERE unique1 IN (1, 2, 3);
                                                      QUERY PLAN                                                       
-----------------------------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on tenk1  (cost=12.88..24.08 rows=3 width=244) (actual time=0.043..0.054 rows=3 loops=1)
   Recheck Cond: (unique1 = ANY ('{1,2,3}'::integer[]))
   Heap Blocks: exact=3
   Buffers: shared hit=5
   ->  Bitmap Index Scan on tenk1_unique1  (cost=0.00..12.88 rows=3 width=0) (actual time=0.026..0.026 rows=3 loops=1)
         Index Cond: (unique1 = ANY ('{1,2,3}'::integer[]))
         Buffers: shared hit=2
 Planning:
   Buffers: shared hit=59
 Planning Time: 0.479 ms
 Execution Time: 0.116 ms
(11 rows)

postgres=# SELECT idx_scan, idx_tup_fetch FROM pg_stat_user_tables WHERE relname = 'tenk1';
 idx_scan | idx_tup_fetch 
----------+---------------
        1 |             3
(1 row)

וכפי שאתה יכול לראות, בPostgres 17 ההתפרצות במאגר המשותף מורדמת ל-5, והכי חשוב, זה עושה רק סקנה אחת במפתח (בעוד שבPostgres 16 היו 3 סקנות). עם השיפור הזה בPostgres 17, הביצועים של הפעולות המצטברות מושכלות בצורה מאוד מעברת, וPostgres יכול לבחור מתוכניות שאלו מותוות יותר.

שימור השותפים הלוגיסטיים וההעלאה של תלויות הרשימה בזמן העדכון

שימור השותפים הלוגיסטיים והעברת התלויות של הרשימה בתהליך עדכון מסיבי הוא תכונה נוספת ברפורמה הלוגיסטית שנוספה לPostgreSQL 17. תשמע על זה שהתכונה תהיה מועילה רק בעדכון מPostgreSQL 17 לגרסות האחרות, זה לא נתמך עבור עדכון לפני Postgres 17. השותפים הלוגיסטיים והמקורות ההדבקה נוצרים בזמן בניית סביבת ההדבקה הלוגיסטית. אך המידע הזה ספציפי לנוד כדי לעדכן את מצב ההדבקה, המצב של היישום, ומצב השדרה של WAL כך שהם לא מעודכנים כחלק מתהליך העדכון. אחרי שהנוד הפרסם מעודכן, המשתמש צריך לבנות ידנית את האובייקטים האלה.

התהליך pg_upgrade מושכל בPostgreSQL 17 על מנת להצג ולשחזר את האובייקטים הפנימיים האלה; הפונקציה הזאת מאפשרת להתרעעות להתחדש באופן אוטומטי בעוד עודכן נקודה בתהליך העדכון שיש לה הדבקה לוגיסטית. לפני כן, בזמן עד

אם אתה רוצה לעדכן קבצן היציעים, עליך לבצע את השלבים הבאים:

  • ודא שכל הרשימות לקבצן היציעים מודעסטות זמנית על-ידי ביצוע ALTER SUBSCRIPTION….DISABLE. הם מואצרים לאחר שהתהליך העדכון הסתיים.
  • שינה את רמת wal_level של הקבצן החדש ל logical.
  • מספר max_replication_slots על הקבצן החדש צריך להיות גדול מאותו של הקבצן הישן או שווה.
  • תוספים היציעים המשמשים על-ידי השירותים צריכים להיות מו Installed בקבצן החדש.
  • כל השינויים מהקבצן הישן כבר מועתקים לקבצן המטרה לפני העדכון.
  • כל השירותים על-ידי הקבצן הישן צריכים להיות יכולים להשתמש; אתה יכול לוודא את זה על-ידי בדיקה של עמודות מתנגשות בתצפית pg_replication_slots. העמודות צריכות להיות לא מתנגשות עבור כל השירותים על-ידי הקבצן הישן.
  • שירותים לא צריכים להיות בקבצן החדש עם ערך false בעמודה Temporary של תצפית pg_replication_slots. לא צריך להיות שירותים ממשקעים לא קבעיים בקבצן החדש.

תהליך pg_upgrade לעדכון שירותים ייצר שגיאה אם אף אחד מהדרישות הקדמיות האלה אינן מוגשות.

סיכויך.

עם PostgreSQL 17, המיקום הקהילתי ממשיך להיות על הגבהת הביצועים של PostgreSQL, הגבלת היכולת, האבטחה והופעתו לשימוש בסוג של ארגון עסקי. Postgres 17 גם משפר את החוויה של המפתחדים על-ידי הוספת תכונות חדשות להתאמה ועל-ידי העצמת תכונות קיימות יותר חזקות ועמידות.

מעבר לגירסה 17, PostgreSQL ימשיך לגדול, לשפר ולהיות יותר בעל ביצועים על-מנת לספק את הדרישות של יישומים עסקיים הדרושים מאחסני מידע סקלטיביים. הסקלטות (גומלין ואנכיין) שוכללו שיפור במשך השנים, אך יש בטח מקום לשיפור באפליקציה הגומלינית על-ידי הוספת יכולת השרדות ל PostgreSQL. אנו נראה יותר שיפורים בהדמיית המחשבה הלוגית, עם עוד שינויים בתחום של השרדות המחשבה הלוגית או השרדות החסרים (כמו סדונים) וטיפול טוב יותר בנקודות. הקהילה גם מזהה את הצורך להגביר את ההתאמה של PostgreSQL, לכן השיפורים בפקודת MERGE ב Postgres 17, ותכניות על תכונות שיותר מהגירסה 17.

Source:
https://dzone.com/articles/postgresql-17-a-major-step-forward-in-performance