PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Разширено съвпадение на дялове за присъединяване по дял

По-рано бях написал блог за присъединяването на дялове в PostgreSQL. В този блог говорих за усъвършенствана техника за съвпадение на дялове, която ще позволи да се използва присъединяване по дялове в повече случаи. В този блог ще обсъдим подробно тази техника.

За да обобщим, основната техника за съвпадение на дялове позволява свързване между две разделени таблици да бъде извършено с помощта на техника за свързване на дялове, ако двете разделени таблици имат точно съвпадащи граници на дял, напр. разделени таблици prt1 и prt2, описани по-долу

psql> \d+ prt1
... [output clipped]
Partition key: RANGE (a)
Partitions: prt1_p1 FOR VALUES FROM (0) TO (5000),
prt1_p2 FOR VALUES FROM (5000) TO (15000),
prt1_p3 FOR VALUES FROM (15000) TO (30000)

и

psql>\d+ prt2
... [ output clipped ]
Partition key: RANGE (b)
Partitions: prt2_p1 FOR VALUES FROM (0) TO (5000),
prt2_p2 FOR VALUES FROM (5000) TO (15000),
prt2_p3 FOR VALUES FROM (15000) TO (30000)

Съединяването между prt1 и prt2 на техния разделен ключ (a) се разбива на съединения между съвпадащите им дялове, т.е. prt1_p1 съединява prt2_p1, prt1_p2 joins prt2_p2 и prt1_p3 joins prt2_p3. Резултатите от тези три свързвания заедно образуват резултата от свързването между prt1 и prt2. Това има много предимства, както беше обсъдено в предишния ми блог. Въпреки това, основното съвпадение на дялове не може да обедини две разделени таблици с различни граници на дял. В примера по-горе, ако prt1 има допълнителен дял prt1_p4 ЗА СТОЙНОСТИ ОТ (30000) ДО (50000), основното съвпадение на дяла няма да помогне за преобразуването на присъединяване между prt1 и prt2 в присъединяване по отношение на дял, тъй като те нямат точно съвпадащ дял граници.

Много приложения използват дялове за разделяне на активно използвани данни и остарели данни, техника, която обсъдих в моя друг блог. Останалите данни в крайна сметка се премахват чрез отпадане на дялове. Създават се нови дялове, за да се поберат свежи данни. Обединяването между две такива разделени таблици ще използва най-вече свързване по дял, тъй като през повечето време те ще имат съвпадащи дялове. Но когато активен дял бъде добавен към една от тези таблици или остарял се изтрие, техните граници на дял няма да съвпадат, докато другата таблица също не претърпи подобна операция. По време на този интервал свързването между тези две таблици няма да използва свързване по дялове и може да отнеме необичайно по-дълго време за изпълнение. Не искаме присъединяване, удрящо базата данни по време на тази малка продължителност, да се представя лошо, тъй като не може да използва присъединяване по дял. Разширеният алгоритъм за съвпадение на дялове помага в този и по-сложни случаи, когато границите на дяла не съвпадат точно.

Разширен алгоритъм за съвпадение на дялове

Разширената техника за съвпадение на дялове открива съвпадащи дялове от две разделени таблици, дори когато техните граници на дял не съвпадат точно. Той намира съвпадащи дялове, като сравнява границите и от двете таблици в сортирания им ред подобно на алгоритъма за обединяване. Всякакви два дяла, по един от всяка от разделената таблица, чиито граници съвпадат точно или се припокриват, се считат за присъединяващи се партньори, тъй като може да съдържат съединяващи се редове. Продължавайки с горния пример, да кажем, че активен нов дял prt2_p4 се добавя към prt4. Разделените таблици сега изглеждат така:

psql>\d+ prt1
... [output clipped]
Partition key: RANGE (a)
Partitions: prt1_p1 FOR VALUES FROM (0) TO (5000),
prt1_p2 FOR VALUES FROM (5000) TO (15000),
prt1_p3 FOR VALUES FROM (15000) TO (30000)

и

psql>\d+ prt2
... [ output clipped ]
Partition key: RANGE (b)
Partitions: prt2_p1 FOR VALUES FROM (0) TO (5000),
prt2_p2 FOR VALUES FROM (5000) TO (15000),
prt2_p3 FOR VALUES FROM (15000) TO (30000),
prt2_p4 FOR VALUES FROM (30000) TO (50000)

Лесно е да видите, че границите на дяловете на prt1_p1 и prt2_p1, prt1_p2 и prt2_p2, и prt1_p3 и prt2_p3 съответно съвпадат. Но за разлика от основното съвпадение на дялове, разширеното съвпадение на дялове ще знае, че prt2_p4 няма съвпадащ дял в prt1. Ако свързването между prt1 и prt2 е INNER присъединяване или когато prt2 е INNER връзка в съединението, резултатът от присъединяването няма да има ред от prt2_p4. Разрешен с подробна информация за съвпадащите дялове и дялове, които не съвпадат, за разлика само от това дали границите на дяла съвпадат или не, оптимизаторът на заявки може да реши дали да използва присъединяване по дял или не. В този случай той ще избере да изпълни присъединяването като присъединяване между съвпадащите дялове, оставяйки prt2_p4 настрана. Но това не прилича много на "разширено" съвпадение на дялове. Нека този път да видим малко по-сложен случай, използвайки разделени на списък таблици:

psql>\d+ plt1
Partition key: LIST (c)
Partitions: plt1_p1 FOR VALUES IN ('0001', '0003'),
plt1_p2 FOR VALUES IN ('0004', '0006'),
plt1_p3 FOR VALUES IN ('0008', '0009')

и

psql>\d+ plt2
Partition key: LIST (c)
Partitions: plt2_p1 FOR VALUES IN ('0002', '0003'),
plt2_p2 FOR VALUES IN ('0004', '0006'),
plt2_p3 FOR VALUES IN ('0007', '0009')

Обърнете внимание, че има точно три дяла и в двете отношения, но списъците със стойности на дяловете се различават. Списъкът, съответстващ на дял plt1_p2 съвпада точно с този на plt2_p2. Освен това няма два дяла, един от двете страни, да имат точно съвпадащи списъци. Разширеният алгоритъм за съвпадение на дялове извежда, че plt1_p1 и plt2_p1 имат припокриващи се списъци и техните списъци не се припокриват с друг дял от другата връзка. По същия начин за plt1_p3 и plt2_p3. Оптимизаторът на заявки след това вижда, че свързването между plt1 и plt2 може да се изпълни като присъединяване на дялове чрез присъединяване на съвпадащите дялове, т.е. plt1_p1 и plt2_p1, plt1_p2 и plt2_p2 и plt1_p3 и plt2_p3 съответно. Алгоритъмът може да намери съвпадащи дялове в още по-сложни обвързани с дял набори от списъци, както и разделени на диапазон таблици. Но няма да ги разглеждаме за краткост. Заинтересованите и по-смелите читатели могат да разгледат ангажимента. Освен това има много тестови примери, които показват различни сценарии, при които се използва усъвършенстван алгоритъм за съвпадение на дялове.

Ограничения

Външни съединения с липсващи съвпадащи дялове от вътрешната страна

Външните съединения представляват особен проблем в света на PostgreSQL. Помислете за prt2 LEFT JOIN prt1, в горния пример, където prt2 е ВЪНШНА релация. prt2_p4 няма присъединяващ се партньор в prt1 и въпреки това редовете в този дял трябва да са част от резултата от свързването, тъй като принадлежат на външната връзка. В PostgreSQL, когато ВЪТРЕШНАТА страна на съединението е празна, тя е представена от "фиктивна" връзка, която не излъчва редове, но все пак знае схемата на тази връзка. Обикновено "фиктивна" връзка се появява от не-фиктивна релация, която няма да излъчи никакви редове поради някаква оптимизация на заявката, като изключване на ограничение. Оптимизаторът на заявки на PostgreSQL маркира такава не-фиктивна връзка като фиктивна и изпълнителят работи нормално, когато изпълнява такова присъединяване. Но когато няма съвпадащ вътрешен дял за външен дял, няма "съществуващ обект", който може да бъде маркиран като "фалшив". Например, в този случай няма prt1_p4, който може да представлява фиктивен вътрешен дял, свързващ външен prt2_p4. В момента PostgreSQL няма начин да "създава" такива "фиктивни" отношения по време на планирането. Следователно оптимизаторът на заявки не използва присъединяване на дялове в този случай.

В идеалния случай такова свързване с празна вътрешна връзка изисква само схема на вътрешната връзка, а не цяла връзка. Тази схема може да бъде извлечена от самата разделена таблица. Всичко, от което се нуждае, е способност за създаване на ред за присъединяване, като се използват колоните от ред във външната страна, съединени с NULL стойности за колоните от вътрешната страна. След като имаме тази способност в PostgreSQL, оптимизаторът на заявки ще може да използва присъединяване по дял дори в тези случаи.

Позволете ми да подчертая, че външните съединения, където няма липсващи дялове във вътрешното съединение, използват присъединяване по разделяне.

Множество съвпадащи дялове

Когато таблиците са разделени така, че множество дялове от едната страна съвпадат с един или повече дялове от другата страна, присъединяването на дялове не може да се използва, тъй като няма начин да се предизвика релация "Добавяне" по време на времето за планиране, което представлява две или повече прегради заедно. Надяваме се, че някога ще премахнем и това ограничение и ще позволим присъединяването на дялове да се използва и в тези случаи.

Хеш разделени таблици

Границите на дялове на две разделени на хеш таблици, използващи същия модул, винаги съвпадат. Когато модулът е различен, ред от даден дял на една таблица може да има своите присъединяващи се партньори в много от дяловете на другата, като по този начин даден дял от едната страна съвпада с множество дялове на другата таблица, като по този начин прави присъединяването на дялове неефективно.

Когато усъвършенстваният алгоритъм за съвпадение на дялове не успее да намери съвпадащи дялове или присъединяването по дял не може да се използва поради горните ограничения, PostgreSQL се връща назад, за да се присъедини към разделените таблици като обикновени таблици.

Разширено време за съвпадение на дял

Саймън повдигна интересен момент, когато коментира функцията. Разделите на разделена таблица не се променят често, така че резултатът от разширеното съвпадение на дялове трябва да остане същият за по-дълго време. Не е необходимо да се изчислява всеки път, когато се изпълнява заявка, включваща тези таблици. Вместо това бихме могли да запазим набора от съвпадащи дялове в някакъв каталог и да го опресняваме всеки път, когато дяловете се променят. Това е известна работа, но си струва времето, прекарано в съпоставянето на дяла за всяка заявка.

Дори и с всички тези ограничения, това, което имаме днес, е много полезно решение, което обслужва повечето практически случаи. Излишно е да казвам, че тази функция работи безпроблемно с FDW join push down, подобрявайки възможностите за разделяне, които 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. SQL:Когато става въпрос за НЕ В и НЕ РАВНО НА, кое е по-ефективно и защо?

  2. Автоматично тестване на процеса на надстройка за PostgreSQL

  3. Как да сравним текущия ред със следващия и предишния ред в PostgreSQL?

  4. Драйвер JDBC PostgreSQL с Android

  5. SQL транспониране на редове като колони