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

Таблица за представяне за PostgreSQL

Производителността е една от най-важните и най-сложни задачи при управлението на база данни. Тя може да бъде повлияна от конфигурацията, хардуера или дори от дизайна на системата. По подразбиране PostgreSQL е конфигуриран с оглед на съвместимостта и стабилността, тъй като производителността зависи много от хардуера и от самата ни система. Можем да имаме система с много четени данни, но информацията не се променя често. Или можем да имаме система, която пише непрекъснато. Поради тази причина е невъзможно да се дефинира конфигурация по подразбиране, която да работи за всички видове натоварвания.

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

ОБЯСНИ

Една от първите стъпки, които можем да предприемем, за да разберем как да подобрим производителността на нашата база данни, е да анализираме направените заявки.

PostgreSQL разработва план за заявка за всяка заявка, която получава. За да видим този план, ще използваме EXPLAIN.

Структурата на план за заявка е дърво от възли на плана. Възлите в долното ниво на дървото са сканиращи възли. Те връщат необработени редове от таблица. Има различни типове възли за сканиране за различни методи за достъп до таблицата. Изходът EXPLAIN има линия за всеки възел в дървото на плана.

world=# EXPLAIN SELECT * FROM city t1,country t2 WHERE id>100 AND t1.population>700000 AND t2.population<7000000;
                               QUERY PLAN                                
--------------------------------------------------------------------------
Nested Loop  (cost=0.00..734.81 rows=50662 width=144)
  ->  Seq Scan on city t1  (cost=0.00..93.19 rows=347 width=31)
        Filter: ((id > 100) AND (population > 700000))
  ->  Materialize  (cost=0.00..8.72 rows=146 width=113)
        ->  Seq Scan on country t2  (cost=0.00..7.99 rows=146 width=113)
              Filter: (population < 7000000)
(6 rows)

Тази команда показва как ще бъдат сканирани таблиците в нашата заявка. Нека видим на какво отговарят тези стойности, които можем да наблюдаваме в нашето EXPLAIN.

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

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

Важно е да се разбере, че цената на възел от по-горно ниво включва цената на всички негови дъщерни възли. Също така е важно да осъзнаете, че цената отразява само нещата, за които се интересува планиращият. По-специално, цената не отчита времето, прекарано в предаването на редове с резултати до клиента, което може да бъде важен фактор за реалното изминало време; но планиращият го игнорира, защото не може да го промени чрез промяна на плана.

Разходите се измерват в произволни единици, определени от параметрите на разходите на планировчика. Традиционната практика е разходите да се измерват в единици извличане на дискови страници; т.е. seq_page_cost обикновено се задава на 1.0 и другите параметри на разходите се задават спрямо това.

ОБЯСНИ АНАЛИЗ

С тази опция EXPLAIN изпълнява заявката и след това показва истинския брой редове и истинското време на изпълнение, натрупано във всеки възел на плана, заедно със същите оценки, които показва обикновеният EXPLAIN.

Нека видим пример за използването на този инструмент.

world=# EXPLAIN ANALYZE SELECT * FROM city t1,country t2 WHERE id>100 AND t1.population>700000 AND t2.population<7000000;
                                                     QUERY PLAN                                                      
----------------------------------------------------------------------------------------------------------------------
Nested Loop  (cost=0.00..734.81 rows=50662 width=144) (actual time=0.081..22.066 rows=51100 loops=1)
  ->  Seq Scan on city t1  (cost=0.00..93.19 rows=347 width=31) (actual time=0.069..0.618 rows=350 loops=1)
        Filter: ((id > 100) AND (population > 700000))
        Rows Removed by Filter: 3729
  ->  Materialize  (cost=0.00..8.72 rows=146 width=113) (actual time=0.000..0.011 rows=146 loops=350)
        ->  Seq Scan on country t2  (cost=0.00..7.99 rows=146 width=113) (actual time=0.007..0.058 rows=146 loops=1)
              Filter: (population < 7000000)
              Rows Removed by Filter: 93
Planning time: 0.136 ms
Execution time: 24.627 ms
(10 rows)

Ако не открием причината, поради която нашите заявки отнемат повече време, отколкото би трябвало, можем да проверим този блог за повече информация.

ВАКУУМ

Процесът VACUUM е отговорен за няколко задачи за поддръжка в рамките на базата данни, една от които възстановяване на паметта, заета от мъртви кортежи. При нормалната работа на PostgreSQL, кортежи, които са изтрити или остарели от актуализация, не се премахват физически от тяхната таблица; те остават налични, докато се извърши ВАКУУМ. Поради това е необходимо периодично да се прави ВАКУУМ, особено в често актуализирани таблици.

Ако VACUUM отнема твърде много време или ресурси, това означава, че трябва да го правим по-често, така че всяка операция да има по-малко за почистване.

Във всеки случай може да се наложи да деактивирате ВАКУУМА, например когато зареждате данни в големи количества.

VACUUM просто възстановява пространството и го прави достъпно за повторна употреба. Тази форма на командата може да работи успоредно с нормалното четене и писане на таблицата, тъй като не се получава изключително заключване. Допълнителното пространство обаче не се връща на операционната система (в повечето случаи); той е достъпен само за повторна употреба в рамките на същата таблица.

VACUUM FULL пренаписва цялото съдържание на таблицата в нов дисков файл без допълнително пространство, което позволява на неизползваното пространство да се върне в операционната система. Този формуляр е много по-бавен и изисква изключително заключване на всяка таблица по време на обработка.

VACUUM ANALYZE извършва VACUUM и след това ANALYZE за всяка избрана таблица. Това е практичен начин за комбиниране на скриптове за рутинна поддръжка.

ANALYZE събира статистически данни за съдържанието на таблиците в базата данни и съхранява резултатите в pg_statistic. Впоследствие инструментът за планиране на заявки използва тези статистически данни, за да помогне при определянето на най-ефективните планове за изпълнение на заявки.

Изтеглете Бялата книга днес Управление и автоматизация на PostgreSQL с ClusterControl Научете какво трябва да знаете, за да внедрите, наблюдавате, управлявате и мащабирате PostgreSQLD Изтеглете Бялата книга

Конфигурационни параметри

За да променим тези параметри, трябва да редактираме файла $ PGDATA / postgresql.conf. Трябва да имаме предвид, че някои от тях изискват рестарт на нашата база данни.

max_connections

Определя максималния брой едновременни връзки към нашата база данни. Има ресурси на паметта, които могат да се конфигурират за всеки клиент, следователно максималният брой клиенти може да предложи максималното количество използвана памет.

superuser_reserved_connections

В случай на достигане на лимита на max_connection, тези връзки са запазени за суперпотребител.

споделени_буфери

Задава количеството памет, което сървърът на базата данни използва за споделени буфери на паметта. Ако имате специален сървър на база данни с 1 GB или повече RAM, разумна първоначална стойност за shared_buffers е 25% от паметта на вашата система. По-големите конфигурации за споделени_буфери обикновено изискват съответно увеличение на max_wal_size, за да се разшири процеса на писане на големи количества нови или модифицирани данни за по-дълъг период от време.

temp_buffers

Задава максималния брой временни буфери, използвани за всяка сесия. Това са локални буфери за сесия, използвани само за достъп до временни таблици. Една сесия ще присвои временните буфери според нуждите до лимита, даден от temp_buffers.

work_mem

Указва количеството памет, което ще се използва от вътрешните операции на ORDER BY, DISTINCT, JOIN и хеш таблиците, преди да се запише във временните файлове на диска. Когато конфигурираме тази стойност, трябва да вземем предвид, че няколко сесии изпълняват тези операции едновременно и всяка операция ще може да използва толкова памет, колкото е посочена от тази стойност, преди да започне да записва данни във временни файлове.

Тази опция се нарича sort_mem в по-старите версии на PostgreSQL.

maintenance_work_mem

Указва максималния обем памет, който операциите по поддръжката ще използват, като ВАКУУМ, СЪЗДАВАНЕ НА ИНДЕКС и ПРОМЕНЯНЕ НА ТАБЛИЦАТА ДОБАВЯНЕ НА ВЪНШЕН КЛЮЧ. Тъй като само една от тези операции може да бъде изпълнена едновременно от сесия и една инсталация обикновено не изпълнява много от тях едновременно, тя може да бъде по-голяма от work_mem. По-големите конфигурации могат да подобрят производителността за VACUUM и възстановяване на база данни.

Когато автоматичното вакуумиране се изпълни, на тази памет може да се присвои броят пъти, в които е конфигуриран параметърът autovacuum_max_workers, така че трябва да вземем това предвид или в противен случай да конфигурираме параметъра autovacuum_work_mem, за да управляваме това отделно.

fsync

Ако fsync е активиран, PostgreSQL ще се опита да се увери, че актуализациите са записани физически на диска. Това гарантира, че клъстерът на базата данни може да бъде възстановен до последователно състояние след срив на операционна система или хардуер.

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

checkpoint_segments (PostgreSQL <9.5)

Максимален брой сегменти на файла със запис между автоматичните контролни точки на WAL (обикновено всеки сегмент е 16 мегабайта). Увеличаването на този параметър може да увеличи времето, необходимо за възстановяване на грешки. В система с много трафик това може да повлияе на производителността, ако е настроена на много ниска стойност. Препоръчва се да се увеличи стойността на checkpoint_segments на системи с много модификации на данни.

Също така добра практика е да записвате WAL файловете на диск, различен от PGDATA. Това е полезно както за балансиране на записа, така и за сигурност в случай на повреда на хардуера.

От PostgreSQL 9.5 конфигурационната променлива "checkpoint_segments" беше премахната и беше заменена с "max_wal_size" и "min_wal_size"

max_wal_size (PostgreSQL>=9.5)

Максималният размер на WAL е позволено да расте между контролните точки. Размерът на WAL може да надвишава max_wal_size при специални обстоятелства. Увеличаването на този параметър може да увеличи времето, необходимо за възстановяване на грешки.

min_wal_size (PostgreSQL>=9.5)

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

wal_sync_method

Метод, използван за принудително актуализиране на WAL на диска. Ако fsync е деактивиран, тази настройка няма ефект.

wal_buffers

Количеството споделена памет, използвана за WAL данни, които все още не са записани на диск. Настройката по подразбиране е около 3% от shared_buffers, не по-малко от 64KB или повече от размера на WAL сегмент (обикновено 16MB). Задаването на тази стойност на поне няколко MB може да подобри производителността на запис на сървър с много едновременни транзакции.

effective_cache_size

Тази стойност се използва от планировчика на заявки, за да вземе предвид планове, които могат или не могат да се поберат в паметта. Това се взема предвид в оценките на разходите за използване на индекс; висока стойност прави по-вероятно да се използват индексни сканирания, а ниската стойност прави по-вероятно да се използват последователни сканирания. Разумна стойност би била 50% от RAM.

default_statistics_target

PostgreSQL събира статистически данни от всяка една от таблиците в своята база данни, за да реши как ще се изпълняват заявките към тях. По подразбиране той не събира твърде много информация и ако не получавате добри планове за изпълнение, трябва да увеличите тази стойност и след това да стартирате ANALYZE в базата данни отново (или да изчакате АВТОВАКУУМ).

синхронно_извършване

Указва дали транзакцията ще изчака записите на WAL да бъдат записани на диска, преди командата да върне индикация за "успех" на клиента. Възможните стойности са:"on", "remote_apply", "remote_write", "local" и "off". Настройката по подразбиране е "включено". Когато е деактивиран, може да има забавяне между времето, когато клиентът се върне, и когато транзакцията е гарантирана, че е защитена срещу заключване на сървъра. За разлика от fsync, деактивирането на този параметър не създава никакъв риск от несъответствие на базата данни:срив на операционната система или базата данни може да доведе до загуба на някои скорошни транзакции, за които се твърди, че са извършени, но състоянието на базата данни ще бъде точно същото, както ако тези транзакции беше отменено чисто. Следователно деактивирането на synchronous_commit може да бъде полезна алтернатива, когато производителността е по-важна от точната сигурност относно трайността на транзакцията.

Регистриране

Има няколко типа данни за регистриране, които може да са полезни или не. Нека видим някои от тях:

  • log_min_error_statement:Задава минималното ниво на регистриране.
  • log_min_duration_statement:Използва се за записване на бавни заявки в системата.
  • log_line_prefix:Придържа информация в началото на всеки ред на регистрационния файл.
  • log_statement:Можете да избирате между NONE, DDL, MOD, ALL. Използването на „всички“ може да причини проблеми с производителността.

Дизайн

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

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

Друг много полезен инструмент е управлението на пула за връзки. Ако имаме система с много натоварване, можем да използваме това, за да избегнем насищането на връзките в базата данни и да можем да ги използваме повторно.

Хардуер

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

  • Памет:Колкото повече RAM имаме, толкова повече данни от паметта можем да обработваме, а това означава по-добра производителност. Скоростта на запис и четене на диска е много по-бавна, отколкото в паметта, следователно, колкото повече информация можем да имаме в паметта, толкова по-добра производителност ще имаме.
  • CPU:Може би няма много смисъл да казвам това, но колкото повече CPU имаме, толкова по-добре. Във всеки случай това не е най-важното по отношение на хардуера, но ако можем да имаме добър процесор, капацитетът ни за обработка ще се подобри и това пряко се отразява на нашата база данни.
  • Твърд диск:Имаме няколко типа дискове, които можем да използваме, SCSI, SATA, SAS, IDE. Имаме и твърдотелни дискове. Трябва да сравним качество/цена, което трябва да използваме, за да сравним скоростта му. Но типът на диска не е единственото нещо, което трябва да вземем предвид, трябва също да видим как да ги конфигурираме. Ако искаме добра производителност, можем да използваме RAID10, запазвайки WAL на друг диск извън RAID. Не се препоръчва използването на RAID5, тъй като производителността на този тип RAID за бази данни не е добра.

Заключение

След като вземем предвид точките, споменати в този блог, можем да извършим сравнителен анализ, за ​​да проверим поведението на базата данни.

Също така е важно нашата база данни да бъде наблюдавана, за да определим дали сме изправени пред проблем с производителността и да можем да го разрешим възможно най-скоро. За тази задача има няколко инструмента като Nagios, ClusterControl или Zabbix, наред с други, които ни позволяват не само да наблюдаваме, но с някои от тях ни позволяват да предприемем проактивни действия, преди да се появи проблемът. С ClusterControl, в допълнение към наблюдението, администрирането и няколко други помощни програми, можем да получаваме препоръки какви действия можем да предприемем, когато получаваме сигнали за производителност. Това ни позволява да имаме представа как да решаваме потенциални проблеми.

Този блог не е предназначен да бъде изчерпателно ръководство за това как да подобрите производителността на базата данни. Да се ​​надяваме, че дава по-ясна картина за това кои неща могат да станат важни и някои от основните параметри, които могат да бъдат конфигурирани. Не се колебайте да ни уведомите, ако сме пропуснали важни.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Заявката на Postgres за проверка на низ е число

  2. съединете две различни таблици и премахнете дублирани записи

  3. какъв е добър начин за хоризонтален шард в postgresql

  4. Как да наблюдавате PostgreSQL, работещ вътре в Docker контейнер:Част първа

  5. Разделете колоната на няколко реда в Postgres