سنتحدث اليوم عن أهم ميزات PostgreSQL 11. لماذا فقط - لأنه لا يحتاج الجميع إلى بعض الميزات ، لذلك استقرنا على أكثر الميزات شعبية.
المحتويات

تجميع Jit
قدم PostgreSQL أخيرًا تجميع JIT ، أي تجميع الاستعلامات في التعليمات البرمجية الثنائية. للقيام بذلك ، قم بترجمة PostgreSQL مع دعم تجميع JIT
(Compile time 1 (--with-llvm))
. في نفس الوقت ، يجب أن يكون للجهاز إصدار LLVM لا يقل عن 3.9.
ما الذي يمكن أن يسرع JIT؟
- استعلامات مع جملة WHERE ، أي كل ما يأتي بعد هذه الكلمة الرئيسية. هذا ليس ضروريًا دائمًا ، لكن الفرصة مفيدة.
- حساب قائمة الهدف: في مصطلحات PostgreSQL ، هذا كل ما بين تحديد ومن.
- المجاميع.
- تحويل السجلات من طريقة عرض إلى أخرى (إسقاط). على سبيل المثال ، عند تطبيق الانضمام على جدولين ، تكون النتيجة مجموعة جديدة تحتوي على حقول من كلا الجدولين.
- تشوه Tuple. إحدى مشاكل أي قاعدة بيانات ، على الأقل صغيرة ، علائقية ، هي كيفية الحصول على حقل من سجل على القرص. بعد كل شيء ، قد يكون هناك قيمة فارغة ، ولديهم سجلات مختلفة وبشكل عام ، هذه ليست العملية الأرخص.
Compile time 2
يعني عدم استخدام JIT. في PostgreSQL هناك لحظة تخطيط الاستعلام ، عندما يقرر النظام ما يستحق JIT وما هو غير ذلك. عند هذه النقطة ، يقوم JITs ثم ينفذ المنفذ كما هو.
JIT قابل للتوصيل. بشكل افتراضي ، يعمل مع LLVM ، ولكن يمكنك توصيل أي JIT أخرى.

إذا جمعت PostgreSQL بدون دعم JIT ، فلن يعمل الإعداد الأول. الخيارات المطبقة للمطورين ، هناك إعدادات لوظائف JIT الفردية.
تتعلق النقطة الدقيقة التالية بـ jit_above_cost. JIT نفسها ليست مجانية. لذلك ، فإن PostgreSQL افتراضيات تحسين JIT إذا تجاوزت تكلفة الاستعلام 100 ألف ببغاء مشروط ، حيث يتم قياس الشرح والتحليل وما إلى ذلك. يتم اختيار هذه القيمة بشكل عشوائي ، لذا انتبه إليها.
ولكن ليس دائمًا بعد تشغيل JIT يعمل كل شيء على الفور. عادة ، يبدأ الجميع في تجربة JIT باستخدام التحديد * من الجدول حيث id = 600 الاستعلام ويفشلون. ربما ، من الضروري تعقيد الطلب بطريقة أو بأخرى ، ثم يقوم الجميع بإنشاء قاعدة بيانات ضخمة وإنشاء الطلب. ونتيجة لذلك ، يعتمد PostgreSQL على إمكانات القرص ؛ ويفتقر إلى سعة المخازن المؤقتة وذاكرة التخزين المؤقت المشتركة.
هنا مثال تجريدي بالكامل. هناك 9 حقول فارغة بترددات مختلفة ، بحيث يمكنك ملاحظة تأثير تشوه tuple.
select i as x1,
case when i % 2 = 0 then i else null end as x2,
case when i % 3 = 0 then i else null end as x3,
case when i % 4 = 0 then i else null end as x4,
case when i % 5 = 0 then i else null end as x5,
case when i % 6 = 0 then i else null end as x6,
case when i % 7 = 0 then i else null end as x7,
case when i % 8 = 0 then i else null end as x8,
case when i % 9 = 0 then i else null end as x9
into t
from generate_series(0, 10000000) i;
vacuum t;
analyze t;
لدى PostgreSQL الكثير من الاحتمالات ، ولرؤية مزايا JIT ، قم بتعطيل أول سطرين حتى لا تتدخل ، وإعادة ضبط العتبات.
set max_parallel_workers=0;
set max_parallel_workers_per_gather=0;
set jit_above_cost=0;
set jit_inline_above_cost=0;
set jit_optimize_above_cost=0;
هنا الطلب نفسه:
set jit=off;
explain analyze
select count(*) from t where
sqrt(pow(x9, 2) + pow(x8,2)) < 10000;
set jit=on;
explain analyze
select count(*) from t where
sqrt(pow(x9, 2) + pow(x8,2)) < 10000;
وها هي النتيجة:
Planning Time: 0.71 ms
Execution Time: 1986.323 ms
VS
Planning Time: 0.060 ms
JIT:
Functions: 4
Generation Time: 0.911 ms
Inlining: true
Inlining Time: 23.876 ms
Optimization: true
Optimization Time: 41.399 ms
Emission Time: 21.856 ms
Execution Time: 949.112 ms
ساعد JIT على تسريع الطلب بمقدار النصف. وقت التخطيط هو نفس الشيء تقريبًا ، ولكن هذا على الأرجح نتيجة تخزين شيء ما في PostgreSQL ، لذا تجاهله.
إذا لخص الأمر ، استغرق الأمر حوالي 80 مللي ثانية لتجميع JIT. لماذا JIT ليست مجانية؟ قبل تنفيذ الطلب ، تحتاج إلى تجميعه ، ويستغرق ذلك أيضًا بعض الوقت. وثلاثة أوامر من الحجم أكثر من التخطيط. ليست متعة باهظة الثمن ، لكنها تؤتي ثمارها بسبب طول التنفيذ.
بهذه الطريقة يمكنك استخدام JIT ، على الرغم من أنها ليست مفيدة دائمًا.
التقسيم
إذا انتبهت إلى التقسيم في PostgreSQL ، فربما لاحظت أنه تم صنعه هناك للعرض. تحسن الوضع قليلاً في الإصدار 10 ، عندما ظهر إعلان تقريبي للأقسام (الأقسام). من ناحية أخرى ، بقي كل شيء كما هو في الداخل وعمل تقريبًا كما كان في الإصدارات السابقة ، أي سيئ.
تم حل هذه المشكلة بطرق عديدة من خلال وحدة pg_pathman ، والتي سمحت بالعمل مع الأقسام وقطعها في الوقت المناسب بما يكفي في وقت التشغيل.
في الإصدار 11 ، تم تحسين التقسيم بشكل كبير:
- أولاً ، قد يحتوي جدول الأقسام على مفتاح أساسي ، والذي يجب أن يتضمن مفتاح القسم. في الواقع ، هذا إما مفتاح شبه أساسي أو شبه مفتاح أساسي. لسوء الحظ ، لا يمكنك عمل مفتاح خارجي عليه. آمل أن يتم إصلاح هذا في المستقبل.
- أيضا الآن من الممكن التقسيم ليس فقط حسب النطاق ، ولكن أيضًا حسب القائمة والتجزئة. يعتبر التجزئة بدائيًا تمامًا ، ويتم أخذ ما تبقى من التعبير له.
- عند التحديث ، يتحرك الخط بين الأقسام. في السابق ، كان عليك كتابة مشغل ، ولكن الآن يتم ذلك تلقائيًا.
السؤال الكبير هو: كم عدد الأقسام التي يمكنني الحصول عليها؟ بصراحة ، مع وجود عدد كبير من الأقسام (الآلاف وعشرات الآلاف) لا تعمل الميزة بشكل جيد. Pg_pathman يعمل بشكل أفضل.
جعل الأقسام أيضا بشكل افتراضي. مرة أخرى ، في pg_pathman يمكنك إنشاء إنشاء تلقائي للأقسام ، وهو أكثر ملاءمة. هنا ، كل شيء لا يمكن دفعه في مكان ما يقع في القسم. إذا كنت في نظام حقيقي للقيام بذلك افتراضيًا ، فعندئذٍ بعد مرور بعض الوقت ، تحصل على مثل هذه الفوضى ، ثم تعذبها.
PostgreSQL 11 قادر الآن على تحسين التقسيم إذا تم ربط جدولين بمفتاح قسم وتطابق مخططات التقسيم. يتم التحكم في ذلك بواسطة معلمة خاصة ، والتي يتم إيقاف تشغيلها افتراضيًا.
يمكنك حساب المجاميع لكل قسم على حدة ، ثم جمعها. أخيرًا ، يمكنك إنشاء فهرس على الجدول المقسم الأصلي ، ثم سيتم إنشاء الفهارس المحلية على جميع الجداول المتصلة به.
في قسم "ما الجديد" ، تم ذكر شيء رائع - القدرة على التخلص من الأقسام عند تنفيذ الطلب. دعونا نتحقق من كيفية عملها. والنتيجة هي مثل هذا الجدول:

نصنع نوعًا وجدولًا من عمودين بمفتاح أساسي ، مع عمود كبير ، ندرج البيانات. نقوم بإنشاء الجدول الثاني ، الذي سيتم تقسيمه وسيكون نسخة من الأول. أضف المفتاح الأساسي إلى الجدول المقسم.

سيتألف الجدول من نوعين من الإدخالات: "المربيات" و "السائقين الذكور". وسيكون هناك سائق واحد. نقوم بعمل قسمين ، مقسومًا على القائمة ، ونضيف المفتاح الأساسي ونضيف جميع البيانات من الجدول الذي يتم إنشاء كل هذا فيه. كانت النتيجة غير مثيرة للاهتمام تمامًا:

انتبه إلى الطلب. نختار كل شيء من جدول غير مقسم ، نتصل بجدول مقسم. نأخذ قطعة صغيرة ونختار نوعًا واحدًا فقط ، يمرون بواحد. نشير إلى أن عمود oss يجب أن يكون له قيمة واحدة. اتضح مجموعة مختارة من المحركات الصلبة.
عند التنفيذ ، نقوم بتعطيل التوازي على وجه التحديد ، لأن PostgreSQL 11 بشكل افتراضي موازٍ بنشاطات أكثر أو أقل تعقيدًا. إذا نظرنا إلى خطة التنفيذ (شرح التحليل) ، فيمكن ملاحظة أن النظام أضاف البيانات في كلا القسمين: في المربية والسائقين ، على الرغم من عدم وجود المربيات. لم تكن هناك مكالمات إلى المخزن المؤقت. الوقت المنقضي ، الحالة المستخدمة ، على الرغم من أن PostgreSQL يمكن أن تكتشف كل ذلك. بمعنى ، لا يعمل إعلان إزالة القسم على الفور. ربما في البنيات التالية سيتم تصحيح هذا. في هذه الحالة ، تعمل وحدة pg_pathman في هذه الحالة دون مشاكل.
المؤشرات
- تحسين عرض الأسعار بطريقة رتيبة ، أي شجرة ب. يعلم الجميع أنه عند إدراج البيانات المتزايدة الرتابة ، لا يتبين أنها سريعة جدًا. أصبح PostgreSQL الآن قادرًا على تخزين الصفحة النهائية في ذاكرة التخزين المؤقت بطريقة خاصة وليس الانتقال من الجذر إلى الإدخال. هذا يسرع العمل بشكل ملحوظ.
- جعلت PostgreSQL 10 من الممكن استخدام فهرس التجزئة لأنه بدأ في استخدام WAL (سجل الكتابة المسبقة). في السابق ، حصلنا على القيمة ، وأفتحنا الصفحة ، وأرجعنا القيمة. للقيمة التالية ، كان عليك حظر الصفحة مرة أخرى والعودة وإلغاء القفل وما إلى ذلك. الآن أصبحت التجزئة أسرع بكثير. يسمح لك بحظر صفحة في كل مرة لاسترداد سجل من فهرس التجزئة ، وإرجاع جميع القيم من هناك وفتحها. الآن يتم تطبيقه لـ HASH و GiST و GIN. في المستقبل ، ربما سيتم تنفيذ ذلك لـ SP-GiST. ولكن بالنسبة لـ BRIN بمنطقه الأدنى / الأقصى ، لا يمكن القيام بذلك من حيث المبدأ.
- إذا كنت تستخدم لبناء فهارس وظيفية ، فقد تم تعطيل التحديث السريع (Heap Only Tuple) بشكل فعال. عندما يتم تحديث السجل في PostgreSQL ، يتم إنشاء نسخة جديدة بالفعل ، وهذا يتطلب اللصق في جميع الفهارس الموجودة في الجدول بحيث تشير القيمة الجديدة إلى المجموعة الجديدة. منذ وقت طويل تم تنفيذ هذا التحسين: إذا لم يغير التحديث الحقول غير المدرجة في الفهارس ، وكانت هناك مساحة خالية على نفس الصفحة ، فلن يتم تحديث الفهارس ، وفي الإصدار القديم من tuple ، يتم وضع مؤشر إلى الإصدار الجديد. يتيح لك ذلك تقليل شدة المشكلة إلى حد ما مع التحديثات. ومع ذلك ، لم يعمل هذا التحسين على الإطلاق إذا كان لديك فهارس وظيفية. في PostgreSQL 11 ، بدأ العمل. إذا قمت ببناء فهرس وظيفي وقمت بتحديث مجموعة لا تغير ما يعتمد عليه الفهرس الوظيفي ، فسيعمل التحديث الساخن.
تغطية المؤشرات
تم تنفيذ هذه الوظيفة بواسطة PostgresPro قبل ثلاث سنوات ، وطوال هذا الوقت حاولت PostgreSQL إضافتها. تغطية الفهارس تعني أنه يمكنك إضافة أعمدة إضافية إلى الفهرس الفريد ، مباشرة في مجموعة الفهرس.
لماذا؟ كل شخص يحب مسح فهرس فقط لعملهم السريع. لهذا ، يتم إنشاء مؤشرات "تغطية" مشروطة:

ولكن في نفس الوقت ، تحتاج إلى الحفاظ على التفرد. لذلك ، يتم بناء مؤشرين ، ضيق وواسع.
العيب هو أنه عند تطبيق الفراغ أو الإدراج أو التحديث على جدول ، يجب عليك تحديث كلا الفهرسين. لذا فإن الإدراج في الفهرس عملية بطيئة. وسيسمح مؤشر التغطية بإدارة مؤشر واحد فقط.
صحيح ، لديه بعض القيود. بتعبير أدق ، الفوائد التي قد لا يتم فهمها على الفور. لا يجب أن يكون العمودان c و d في فهرس الإنشاء الأول من الأنواع العددية التي يتم تحديد فهرس b-tree لها. أي أنه ليس لديهم بالضرورة مقارنة أقل. يمكن أن تكون نقاط أو مضلعات. الشيء الوحيد هو أنه يجب أن يكون عدد الصفوف أقل من 2.7 كيلوبايت ، لأنه لا يوجد نخب في المؤشر ، ولكن يمكنك احتواء ذلك الذي لا يمكن مقارنته.
ومع ذلك ، داخل الفهرس مع هذه الأعمدة المغطاة المضمونة ، لا يتم إجراء حسابات عند البحث. يجب أن يتم ذلك عن طريق مرشح يقف فوق الفهرس. من ناحية ، لماذا لا تحسبه داخل الفهرس ، من ناحية أخرى ، هذه مكالمة دالة إضافية. لكن كل شيء ليس مخيفا كما يبدو.
حسنًا ، بالإضافة إلى ذلك ، يمكنك إضافة هذه الأعمدة المغطاة إلى المفتاح الأساسي.
SP جست
قليل من الناس يستخدمون هذا المؤشر لأنه محدد تمامًا. ومع ذلك ، أصبح من الممكن تخزين ما لم يتم إدخاله. هذا يشير إلى مؤشر الفقد والضغط. خذ المضلعات كمثال. بدلاً من ذلك ، يتم وضع مربع محيط في الفهرس ، أي الحد الأدنى من المستطيل الذي يحتوي على المضلع المطلوب. في هذه الحالة ، نمثل المستطيل كنقطة في الفضاء الرباعي الأبعاد ، ثم نعمل مع الرباعي الكلاسيكي في الفضاء الرباعي الأبعاد.
أيضا ل SP-GiST قدم عملية "البحث البادئة". تقوم بإرجاع true إذا كان سطر ما بادئة لسطر آخر. لقد قدموه ليس فقط بهذه الطريقة ، ولكن من أجل مثل هذا الطلب مع دعم SP-GiST.
SELECT * FROM table WHERE c ^@ „abc“
في b-tree هناك حد 2.7 كيلوبايت لكل سطر ، ولكن SP-GiST لا. صحيح أن PostgreSQL لها قيود: لا يمكن أن تتجاوز القيمة الواحدة 1 جيجابايت.
الأداء
- لقد ظهر مسح الصورة النقطية فقط . إنه يعمل مثل المسح الضوئي الكلاسيكي فقط ، باستثناء أنه لا يمكن أن يضمن أي أمر. لذلك ، ينطبق فقط على بعض المجاميع مثل count (*) ، لأن الصورة النقطية غير قادرة على نقل الحقول من الفهرس إلى المنفذ. يمكنه فقط الإبلاغ عن حقيقة سجل يستوفي الشروط.
- الابتكار القادم هو تحديث خريطة الفضاء الحر أثناء تطبيق الفراغ . لسوء الحظ ، لا يعتقد أي من مطوري الأنظمة التي تعمل مع PostgreSQL أنه من الضروري الحذف في نهاية الجدول ، وإلا ستظهر فجوات ، مساحة غير مخصصة. لتتبع هذا ، قمنا بتطبيق FSM ، مما يسمح لنا ليس بتكبير الجدول ، ولكن لإدخال tuple في الفراغات. في السابق ، تم ذلك باستخدام الفراغ ، ولكن في النهاية. والآن أصبح الفراغ قادرًا على القيام بذلك في العملية ، وفي الأنظمة المحملة بشكل كبير يساعد على إبقاء حجم الطاولة تحت السيطرة.
- إمكانية تخطي مسح المؤشر أثناء تنفيذ الفراغ . والحقيقة هي أن جميع فهارس PostgreSQL ، وفقًا لنظرية قاعدة البيانات ، تسمى ثانوية. وهذا يعني أنه يتم تخزين الفهارس بعيدًا عن الجدول ، وتؤدي المؤشرات إليها. يسمح لك الفهرس فقط بعدم القيام بهذه القفزة على المؤشرات ، ولكن يمكنك أخذها مباشرة من الفهرس. لكن الفراغ ، الذي يحذف السجلات ، لا يمكنه النظر إليها في الفهرس وتحديد ما إذا كان سيتم حذفها أم لا ، ببساطة لأنه لا توجد مثل هذه البيانات في الفهرس. لذلك ، يتم إجراء التفريغ دائمًا بمرورين. أولاً ، يتصفح الجدول ويكتشف ما يحتاج إلى حذفه. ثم يذهب إلى الفهارس المرفقة بهذا الجدول ، ويحذف السجلات التي تشير إلى الموجود ، ويعود إلى الجدول ويحذف ما كان عليه. ومرحلة الذهاب إلى المؤشرات ليست مطلوبة دائمًا.
إذا لم يكن هناك أي حذف أو تحديث منذ الفراغ الأخير ، فلا يوجد لديك سجلات ميتة ، فلا حاجة إلى حذفها. في هذه الحالة ، لا يمكنك الذهاب إلى الفهرس. هناك خفايا إضافية ، لا تحذف b-tree صفحاتها على الفور ، ولكن في مرورين. لذلك ، إذا حذفت الكثير من البيانات في الجدول ، فأنت بحاجة إلى إجراء فراغ. ولكن إذا كنت تريد تحرير مساحة في المؤشرات ، فقم بالمكنسة الكهربائية مرتين.
سيتفاجأ شخص ما ، ما هذا الجدول الذي لم يتم فيه حذف أو تحديث؟ في الواقع ، الكثير يتعامل مع هذا ، لا أعتقد. هذه هي جداول إلحاق فقط ، حيث ، على سبيل المثال ، يتم إضافة السجلات. فيها ، الإزالة نادرة للغاية. وهذا يوفر إلى حد كبير مدة الفراغ / الفراغ التلقائي ، ويقلل من الحمل على القرص ، واستخدام ذاكرة التخزين المؤقت وما إلى ذلك. - الالتزام بالمعاملات التنافسية في وقت واحد . هذا ليس ابتكارًا ، ولكنه تحسن. يكتشف PostgreSQL الآن أنه سيلتزم به الآن ، ويؤخر تنفيذ المعاملة الحالية ، بانتظار بقية عمليات الالتزام. يرجى ملاحظة أن هذه الميزة لها تأثير ضئيل إذا كان لديك خادم صغير مع 2-4 نوى.
- postgres_fdw (أغلفة البيانات الخارجية) . FDW هي طريقة لتوصيل مصدر بيانات خارجي بحيث تبدو وكأنها حقيقية بعد المؤتمر. يسمح لك postgres_fdw بتوصيل جدول من مثيل مجاور بمثيلك ، وسيبدو تقريبًا مثل جدول حقيقي. الآن تمت إزالة أحد قيود التحديث والحذف. غالبًا ما يمكن لـ PostgreSQL تخمين أنك بحاجة إلى إرسال البيانات الأولية. طريقة تنفيذ طلب الانضمام بسيطة للغاية: ننفذه على أجهزتنا ، نسحب الجدول من المثيل باستخدام FDW ، ونكتشف المفتاح الأساسي للمعرف الذي نحتاج إلى حذفه ، ثم نطبق التحديث و / أو الحذف ، أي البيانات التي نرجعها ذهابًا وإيابًا . الآن من الممكن القيام به. بالطبع ، إذا كانت الطاولات على أجهزة مختلفة ، فهذا ليس سهلاً للغاية ، لكن FDW تسمح لك بإجراء العمليات عن بُعد ، وانتظرنا للتو.
- toast_tuple_target . هناك حالات عندما تتجاوز البيانات بشكل طفيف الحدود التي يلزم بعدها التحميص ، ولكن في نفس الوقت ، لا يكون نخب هذه القيم لطيفًا دائمًا. لنفترض أن لديك حدًا يبلغ 90 بايت ، وتحتاج إلى احتواء 100. عليك أن تبدأ في نخب لمدة 10 بايت ، قم بإضافتها بشكل منفصل ، ثم عند تحديد هذا الحقل ، تحتاج إلى الانتقال إلى فهرس النخب ، ومعرفة مكان البيانات اللازمة ، انتقل إلى جدول الخبز. جمع وإعطاء.
الآن بمساعدة الضبط الدقيق ، يمكنك تغيير هذا السلوك لقاعدة البيانات بأكملها أو جدول منفصل بحيث لا تتطلب مثل هذه المخارج الصغيرة استخدام نخب. ولكن يجب أن تفهم ما تفعله ، بدون هذا ، لن ينجح أي شيء.
WAL
- WAL (سجل قبل الكتابة) هو سجل قبل الكتابة. تم تعيين حجم مقطع WAL في initdb. الحمد لله ، ليس عند تجميع.
- لقد تغير المنطق أيضا. سابقًا ، تم حفظ مجموعة مقاطع WAL من لحظة نقطة التفتيش قبل الأخيرة ، والآن من الأخيرة. هذا يمكن أن يقلل بشكل كبير من كمية البيانات المخزنة. ولكن إذا كان لديك قاعدة بيانات 1 تيرابايت ، و TPS = 1 ، أي طلب واحد في الثانية ، فلن ترى الفرق.
النسخ الاحتياطي والتكرار
- ظهر Truncate في النسخ المتماثل المنطقي . كانت آخر عمليات DML التي لم تنعكس في النسخ المتماثل المنطقي. ينعكس الآن.
- ظهرت رسالة حول التحضير في النسخ المتماثل المنطقي . الآن يمكنك التقاط عملية التحضير ، التزام على مرحلتين في النسخ المتماثل المنطقي. يتم تنفيذ هذا لبناء مجموعات - غير متجانسة ، متجانسة ، حادة وغير مظللة ، متعددة الوسائط وما إلى ذلك.
- استثناء من جداول pg_basebackup المؤقتة وغير المسجلة . اشتكى الكثير من أن pg_basebackup يتضمن الجداول المدرجة. وباستثناءها ، نقوم بتقليل حجم النسخة الاحتياطية. ولكن بشرط أن تستخدم جداول مؤقتة وغير مسجلة ، وإلا فسيكون هذا الخيار عديم الفائدة بالنسبة لك.
- التحكم في Checksumma في تدفق النسخ المتماثل (للجداول) . هذا يسمح لك بفهم ما حدث للنسخة المتماثلة الخاصة بك. حتى الآن ، يتم تنفيذ الوظيفة للجداول فقط.
- كان هناك ترقية لمواقع فتحة النسخ المتماثل . كما هو الحال دائمًا ، يمكنك فقط التقدم للأمام ، والعودة فقط إذا كان هناك WAL. علاوة على ذلك ، عليك أن تفهم جيدًا ما تفعله به ولماذا. في رأيي ، هذا أكثر من خيار تطوير ، ولكن يمكن لأولئك الذين يستخدمون النسخ المتماثل المنطقي لبعض التطبيقات الغريبة الاستمتاع به.
بالنسبة لـ dba
- تعديل الجدول ، إضافة عمود ، وليس فارغًا افتراضيًا X ، اكتب الجدول بأكمله. هناك رسوم رمزية لهذا: يتم تخزين القيمة الافتراضية بشكل منفصل. إذا قمت باختيار مجموعة تتطلب هذا العمود ، فستضطر PostgreSQL إلى اتباع مسار ترميز إضافي لسحب قيمة مؤقتة ، واستبدالها في مجموعة وتعطيها لك. ومع ذلك ، يمكن للمرء أن يعيش معها.
- فراغ / تحليل . في السابق ، كان يمكنك فقط تطبيق الفراغ أو التحليل على قاعدة بيانات كاملة أو جدول واحد. الآن من الممكن القيام بذلك لعدة جداول ، مع أمر واحد.
التنفيذ الموازي
- البناء الموازي لمؤشرات b-tree . في الإصدار 11 ، أصبح من الممكن تضمين فهارس b-tree في العديد من العمال. إذا كان لديك جهاز جيد بالفعل ، والعديد من الأقراص والعديد من النوى ، فيمكنك بناء فهارس بالتوازي ، وهذا يعد بزيادة ملحوظة في الأداء.
- تجزئة الاتصال المتوازي باستخدام جدول التجزئة المشترك للمنفذين . , -. , . - , . .
- , union, create table as, select create materialized view!
- - (limit) . .
:
alter table usr reset (parallel_workers)
create index on usr(lower((so).occ)) — 2
alter table usr set (parallel_workers=2)
create index on usr(upper((so).occ)) — 1.8
parallel worker. . 16 4 ( ) 2 ., — 1,8 . , , . , .
:
explain analyze
select u1.* from usr u, usr1 u1 where
u.id=u1.id+0
, . , user — , . . , , .
, PostgreSQL 11 .

1425 , 1,5 . 1,4 . 2 . , 9.6 : 1 — 1 ., 2 1 . , 10 tuple. 11 . : user, batch, x-scan append .
:

. 211 , 702 . , 510 1473. , 2 .
parallel hash join. . — 4. , .
parallel index scan . batch . ? hash join, . user . , parallel hash, .
1 . , OLAP-, OLTP . OLTP , .
.
- . , . , «» «», index scan, . (highly skewed data), , . . , , .
- «», .
Window-
SQL:2011, .
, , . , , , , , .
websearch, . , . , .
# select websearch_to_tsquery('dog or cat');
----------------------
'dor' | 'cat'
# select websearch_to_tsquery('dog -cat');
----------------------
'dor' & !'cat'
# select websearch_to_tsquery('or cat');
----------------------
'cat'
— dog or cat — . Websearch . | , . “or cat”. , . websearch “or” . , -, .
Websearch — . : , . , .
Json(b)
10- , 11- . json json(b), tsvector. ( json(b)) - . , , , bull, numeric, string, . .
# select jsonb_to_tsvector
('{"a":"texts", "b":12}', '"string"');
-------------------
'text':1
# select jsonb_to_tsvector
('{"a":"texts", "b":12}', '["string", "numeric"]');
-------------------
'12':3 'text':1
json(b), . , , , .
PL/*
.
CREATE PROCEDURE transaction_test1()
LANGUAGE plpgsql
AS $$
BEGIN
FOR i IN 0..9 LOOP
INSERT INTO test1 (a) VALUES (i);
IF i % 2 = 0 THEN
COMMIT;
ELSE
ROLLBACK;
END IF;
END LOOP;
END
$$;
CALL transaction_test1();
call, , . . . select, insert .
, , PostgreSQL . Perl, Python, TL PL/pgSQL. Perl sp begin, .
PL/pgSQL : , .
pgbench
pgbench ICSB bench — , , . if, , . case, - .
--init-steps
, , .
random-seed. zipfian- . / — , . - , , - , .
, , - .
PSQL
, PSQL, . exit quit.
- — copy, 2 32 . copy : 2 32 - . , 2 31 2 32 copy . 64- , 2 64 .
- POSIX : NaN 0 = 1 1 NaN = 1.