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

Намек за PostgreSQL

Тази седмица пламенната война в списъка с производителност на pgsql отново се върти около факта, че PostgreSQL няма традиционния синтаксис на подсказки, наличен в други бази данни. За това има комбинация от технически и прагматични причини:

  • Въвеждането на съвети е често срещан източник на по-късни проблеми, тъй като фиксирането на място на заявка веднъж в специален случай не е много надежден подход. Тъй като наборът ви от данни нараства и вероятно променя разпределението, идеята, за която сте намекнали, когато е била малка, може да стане все по-лоша идея.
  • Добавянето на полезен интерфейс за подсказки би усложнило кода на оптимизатора, който е достатъчно труден за поддържане такъв, какъвто е. Част от причината, поради която PostgreSQL работи толкова добре, колкото изпълнява заявките, е защото кодът, който се чувства добре, („можем да отметнем намекването на нашия списък с функции за сравнение на доставчици!“), който всъщност не плаща за себе си по отношение на създаването на базата данни достатъчно по-добър, за да оправдае продължаващото му поддържане, се отхвърля от политиката. Ако не работи, няма да бъде добавен. И когато се оценяват обективно, съветите са средно проблем, отколкото решение.
  • Видът на проблеми, които подсказват, че работят, могат да бъдат грешки в оптимизатора. Общността на PostgreSQL реагира на истински грешки в оптимизатора по-бързо от всеки друг в индустрията. Разпитайте наоколо и не е нужно да се срещате с много потребители на PostgreSQL, преди да намерите някой, който е съобщил за грешка и е гледал как се коригира до следващия ден.

Сега, основният напълно валиден отговор на откриването на липса на подсказки, обикновено от администратори на база данни, които са свикнали с тях, е „е как да се справя с грешка в оптимизатора, когато се сблъскам с нея?“ Както всяка технологична работа в днешно време, обикновено има огромен натиск да се получи възможно най-бързото поправяне, когато се появи проблем с лоша заявка.
Ако PostgreSQL нямаше начини да се справи с тази ситуация, нямаше да има сериозни производствени PostgreSQL бази данни . Разликата е, че нещата, които коригирате в тази база данни, се коренят повече във влиянието на решенията, които оптимизаторът вече взема по доста фин начин, а не просто вие да му казвате какво да прави. Това са намеци в буквалния смисъл на думата, те просто нямат някакъв потребителски интерфейс за намекване, че потребителите на други бази данни, нови за PostgreSQL, търсят.
Имайки това предвид, нека да разгледаме какво можете да направите в PostgreSQL, за да заобиколите лоши планове за заявки и грешки в оптимизатора, особено нещата, които много хора смятат, че могат да бъдат решени само с намеци:

  • join_collapse_limit:  Това регулира колко гъвкавост трябва да има оптимизаторът за пренареждане на обединения на множество таблици. Обикновено се опитва всяка възможна комбинация, когато съединенията могат да бъдат пренаредени (което е през повечето време, освен ако не използвате външно съединение). Намаляването на join_collapse_limit, може би дори до 1, премахва част или цялата тази гъвкавост. Когато е зададено на 1, ще получите присъединяванията в реда, в който сте ги написали, точка. Планирането на голям брой присъединявания е едно от най-трудните неща за оптимизатора; всяко присъединяване увеличава грешките в оценките и увеличава времето за планиране на заявката. Ако основният характер на вашите данни прави очевидно какъв ред на обединяването трябва да се случи и не очаквате това някога да се промени, след като разберете правилния ред, можете да го заключите с помощта на този параметър.
  • random_page_cost:  По подразбиране на 4.0, този параметър задава колко скъпо е търсенето на диск за намиране на произволна страница на диска спрямо референтна стойност от 1.0. Сега, в действителност, ако измерите съотношението на произволен към последователен I/O на обикновени твърди дискове, ще откриете, че това число е по-близо до 50.  Така че защо 4.0? Първо, защото е отработено по-добре от по-големите стойности при тестване в общността. Второ, в много случаи по-специално индексните данни ще бъдат кеширани в паметта, което прави ефективните разходи за четене на тези стойности по-ниски. Ако, например, вашият индекс е 90% кеширан в RAM, това означава, че 10% от времето ще извършвате операцията, която е 50X по-скъпа; това би направило ефективната ви random_page_cost около 5.  Този вид ситуация в реалния свят е причината по подразбиране да има смисъл къде се намира. Обикновено виждам, че популярните индекси получават>95% кеш в паметта. Ако всъщност е много по-вероятно вашият индекс да бъде в RAM, намаляването на random_page_cost до малко над 1.0 може да бъде разумен избор, за да се отрази, че не е по-скъпо от всяко друго четене. В същото време, произволните търсения на наистина натоварени системи могат да бъдат много по-скъпи от очакванията, които бихте имали само при разглеждане на симулации за един потребител. Трябваше да задам random_page_cost до 60, за да накарам базата данни да спре да използва индекси, когато плановникът погрешно прецени колко скъпи ще бъдат те. Обикновено тази ситуация идва от грешка в оценката на чувствителността от страна на планировщика – ако сканирате повече от около 20% от таблицата, той знае, че използването на последователно сканиране ще бъде много по-ефективно от индексното сканиране. Грозната ситуация, при която трябваше да принудя това поведение да се случи много по-рано от това, се случи, когато планиращият очакваше да бъдат върнати 1% от редовете, но всъщност беше по-близо до 15%.
  • work_mem:  Коригира колко памет е налична за заявки, извършващи сортиране, хеширане и подобни операции, базирани на памет. Това е само груба насока за заявките, а не твърдо ограничение и един клиент може в крайна сметка да използва кратни work_mem, когато изпълнява заявка. Съответно, трябва да внимавате да не зададете тази стойност твърде висока във файла postgresql.conf. Това, което можете да направите вместо това, обаче, той го задава, преди да стартира заявка, която наистина се възползва от наличието на допълнителна памет за съхранение на данни за сортиране или хеширане. Понякога можете да намерите тези заявки от регистриране на бавни, като използвате log_min_duration_statement. Можете също да ги намерите, като включите log_temp_files, който ще се регистрира всеки път, когато work_mem е твърде малък и следователно операциите по сортиране се прехвърлят на диск, вместо да се случват в паметта.
  • ОТМЕСТВАНЕ 0:  PostgreSQL ще пренареди подзаявките под формата на присъединяване, така че след това да може да използва обикновената логика на реда на присъединяване, за да го оптимизира. В някои случаи това решение може да бъде наистина лошо, тъй като нещата, които хората са склонни да пишат като подзаявки, изглеждат малко по-трудни за оценка по някаква причина  (казвам това въз основа на броя на подобни обезпокоителни заявки, които виждам). Един подъл трик, който можете да направите, за да предотвратите тази логика, е да поставите OFFSET 0 в края на подзаявката. Това не променя резултатите, но вмъкването на типа възел на Limit заявка, използван за изпълнение на OFFSET, ще предотврати пренареждането. След това подзаявката винаги ще се изпълнява по начина, по който повечето хора очакват – като свой собствен изолиран възел на заявка.
  • enable_seqscan, enable_indexscan, enable_bitmapscan:  Изключването на една от тези функции за търсене на редове в таблица е доста голям чук, за да препоръчате силно да избягвате този тип сканиране (не винаги го предотвратявате – ако няма начин да изпълните плана си, но сексканиране, ще получите сексканиране дори ако параметрите са изключени). Основното, за което ги препоръчвам, е да не коригирате заявки, а да експериментирате с EXPLAIN и да видите защо другият тип сканиране е предпочитан.
  • enable_nestloop, enable_hashjoin, enable_mergejoin:  Ако подозирате, че проблемът ви е в типа на свързване, което се използва, а не в това как се четат таблиците, опитайте да изключите типа, който виждате в плана си, като използвате един от тези параметри, след което изпълнете EXPLAIN отново. Грешките в оценките за чувствителност могат лесно да направят присъединяването да изглежда повече или по-малко ефективно, отколкото е в действителност. И отново, виждането как планът се променя с деактивиран текущ метод на присъединяване може да бъде много информативен за това защо изобщо е избрал този.
  • enable_hashagg, enable_material:  Тези функции са сравнително нови за PostgreSQL. Агресивното използване на Hash Aggregation беше въведено във версия 8.4, а по-агресивната материализация във версия 9.0. Ако виждате тези типове възли във вашия EXPLAIN
    изход и изглежда, че правят нещо нередно, защото този код е много по-нов, че е малко по-вероятно да има ограничение или грешка, отколкото някои от по-старите функции. Ако сте имали план, който работи добре в по-старите версии на PostgreSQL, но използва един от тези типове възли и изглежда, че работи много по-лошо в резултат, деактивирането на тези функции понякога може да ви върне към по-ранното поведение – както и да хвърли малко светлина върху защо оптимизаторът е направил грешното нещо като полезна обратна връзка. Имайте предвид, че обикновено това е начинът, по който по-разширените функции обикновено се въвеждат в PostgreSQL:  с опцията да го изключите за целите на отстраняване на неизправности, ако се окаже, че има регресия на плана спрямо начина, по който по-ранните версии са изпълнявали нещата.
  • cursor_tuple_fraction:  Ако не възнамерявате да прочетете всички редове обратно от заявка, трябва да използвате курсор, за да приложите това. В този случай оптимизаторът се опитва да даде приоритет дали ви връща първия ред бързо, или предпочита да оптимизира цялата заявка въз основа на този параметър. По подразбиране базата данни приема, че ще четете отново 10% от заявката, когато използвате курсор. Регулирането на този параметър ви позволява да го наклоните към очакване да четете по-малко или повече от това.

Всички тези параметри и корекции на заявката трябва да бъдат обмислени за корекции на сортиране. Не искате да работите с тях на място завинаги (освен може би за join_collapse_limit). Използвате ги, за да се измъкнете от задръстване и след това се надяваме, че ще разберете каква е истинската основна причина за лошия план – лоша статистика, ограничение/бъг на оптимизатора или нещо друго – и след това ще се справите с проблема от тази посока. Колкото повече насочвате поведението на оптимизатора в определена посока, толкова по-изложени сте на бъдещи промени във вашите данни, което прави това натискане вече неправилно. Ако ги използвате правилно, като начин да проучите защо сте получили грешен план (подходът, който използвах в главата за оптимизация на заявките на PostgreSQL 9.0 High Performance), начинът, по който намеквате за нещата в 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. Може ли PostgreSQL да извърши свързване между две съхранени процедури на SQL Server?

  2. Вземете размера на всички бази данни в PostgreSQL (psql)

  3. Завъртане на множество колони с помощта на Tablefunc

  4. Използване на автоматизация за ускоряване на тестовете за издаване на PostgreSQL

  5. Таблица Печат не отговаря на размера на страницата