{"id":14973943,"url":"https://github.com/hyperion-cs/pgsql_faq","last_synced_at":"2025-12-27T10:28:50.928Z","repository":{"id":63170783,"uuid":"565711796","full_name":"hyperion-cs/pgsql_for_beginners","owner":"hyperion-cs","description":":elephant: PostgreSQL: Ответы на часто задаваемые вопросы начинающих DBA / FAQ for DBA beginners.","archived":false,"fork":false,"pushed_at":"2025-01-31T20:33:26.000Z","size":22,"stargazers_count":5,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-31T21:26:38.008Z","etag":null,"topics":["beginner","dba","dbms","faq","pgsql","postgresql"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hyperion-cs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-11-14T06:53:22.000Z","updated_at":"2025-01-31T20:33:30.000Z","dependencies_parsed_at":"2024-10-11T09:41:22.386Z","dependency_job_id":"a4bd3b01-3a55-4b57-b1e8-3d07f1303247","html_url":"https://github.com/hyperion-cs/pgsql_for_beginners","commit_stats":{"total_commits":15,"total_committers":2,"mean_commits":7.5,"dds":0.06666666666666665,"last_synced_commit":"348fe8c32acf9467bd3727a15e802dd09e793097"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hyperion-cs%2Fpgsql_for_beginners","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hyperion-cs%2Fpgsql_for_beginners/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hyperion-cs%2Fpgsql_for_beginners/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hyperion-cs%2Fpgsql_for_beginners/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hyperion-cs","download_url":"https://codeload.github.com/hyperion-cs/pgsql_for_beginners/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238437657,"owners_count":19472458,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["beginner","dba","dbms","faq","pgsql","postgresql"],"created_at":"2024-09-24T13:49:43.163Z","updated_at":"2025-10-27T05:31:01.441Z","avatar_url":"https://github.com/hyperion-cs.png","language":null,"readme":"# :elephant: PostgreSQL – FAQ\n\nОтветы на часто задаваемые вопросы / FAQ.\n\n## Введение\n\n:exclamation: В первую очередь, мы должны уметь думать **самостоятельно**.\nВ особенности, это касается проблем, которые у вас возникают\n— сначала тщательно и усердно попытайтесь [нагуглить](https://www.google.com/) решение, и только в случае неудачи задавайте вопросы (_как это делать правильно — см. ниже_).\u003cbr\u003e\nУважайте время и труд других участников сообщества, общайтесь исключительно в вежливой манере.\nЭто первостепенные и необходимые условия для того, чтобы приумножать свои навыки и расти как профессионал.\n\n## Оглавление / Table of Contents\n\n\u003c!-- Тэг \u003cbr\u003e необходим для корректной работы вложенных списков. --\u003e\n\n1. [Сообщество](#1-community)\n2. [Вопросы](#2-questions)\u003cbr\u003e\n    2.1. [Не могу подсоединиться к PostgreSQL. Что делать?](#2.1-connection-problem)\u003cbr\u003e\n    2.2. [Получаю ошибку что имя таблицы/колонки/etc неверное, хотя это не так. В чем дело?](#2.2-name-does-not-exist)\u003cbr\u003e\n    2.3. [Как публиковать SQL запросы, определения функций, выводы команд вспомогательных утилит и прочую текстовую информацию при запросе помощи у сообщества?](#2.3-data-publication)\u003cbr\u003e\n    2.4. [У меня медленно работает SQL запрос и я хочу попросить помощи у сообщества. Какую информацию мне необходимо предоставить?](#2.4-slow-query)\u003cbr\u003e\n    2.5. [У меня не получается написать SQL запрос/etc и/или я получаю ошибки. Какую информацию мне необходимо предоставить для получения помощи от сообщества?](#2.5-invalid-query)\u003cbr\u003e\n    2.6. [В каком стиле писать код и идентификаторы в PostgreSQL?](#2.6-coding-style)\u003cbr\u003e\n    2.7. [Секционирование (партиционирование)](#2.7-partitioning)\u003cbr\u003e\n    - 2.7.1. [Какие убедительные причины (не)использования секционирования?](#2.7.1-partitioning-reasons-for-use)\u003cbr\u003e\n    - 2.7.2. [Какие плюсы и минусы есть у секционирования?](#2.7.2-partitioning-pros-and-cons)\u003cbr\u003e\n    - 2.7.3. [Какие нюансы есть при работе с секционированием?](#2.7.3-partitioning-nuances)\u003cbr\u003e\n\n    2.8. [База/таблица весит больше чем я ожидаю, что делать?](#2.8-fat-dbms)\u003cbr\u003e\n    2.9. [Как работает тип _timestamp with time zone_?](#2.9-timestamptz)\u003cbr\u003e\n    2.10. [Что не так со звездочками _(*)_?](#2.10-why-asterisk-is-bad)\u003cbr\u003e\n    2.11. [Утилита pg_dump создает бэкапы?](#2.11-pgdump_is_not_backup)\u003cbr\u003e\n\n3. [Книги/курсы](#3-learning)\n4. [Полезные ссылки](#4-links)\n5.  [Переводы / Translations](translations)\u003cbr\u003e\n    5.1. [English](translations/ENG.md)\n\n## \u003ca name='1-community' /\u003e [1.](#1-community) Сообщество :family_man_woman_girl_boy:\n\nУ PostgreSQL прекрасное сообщество, которое обладает, в том числе, заметным свойством толерантности к начинающим участникам.\nСреди основных точек входа стоит отметить следующие:\n\n1. [Чат русскоязычного сообщества PostgreSQL в Telegram](https://t.me/pgsql);\n2. [PGDay.ru](https://pgday.ru/) - Ежегодная конференция по PostgreSQL (Санкт-Петербург);\n3. [PGConf.ru](https://pgconf.ru/) - Ежегодная конференция по PostgreSQL (Москва).\n\n\n## \u003ca name='2-questions' /\u003e [2.](#2-questions) Вопросы :interrobang:\n\n### \u003ca name='2.1-connection-problem' /\u003e [2.1.](#2.1-connection-problem) Не могу подсоединиться к PostgreSQL. Что делать?\n\nПожалуй, это наиболее частый вопрос у начинающих пользователей PostgreSQL, ежедневно звучащий в информационной среде сообщества.\nКак правило, они получают ошибки, содержащие ключевые слова `Connection refused` или `Connection ... failed`. Например:\n```\nerror: connection to server at \"localhost\", port 5432 failed: Connection refused \n```\nили (в случае попытки подключения через [unix domain socket](https://en.wikipedia.org/wiki/Unix_domain_socket)):\n```\nerror: connection to server on socket \"/var/run/postgresql/.s.PGSQL.5432\" failed: No such file or directory\n    Is the server running locally and accepting connections on that socket?\n```\n\nСледует провести диагностику проблемы поэтапно (_в настоящее время инструкция применительна только для Unix-based ОС_):\n\n#### 2.1.1. Запущен ли основной процесс PostgreSQL?\n\nПосмотреть, запущен ли основной процесс PostgreSQL, можно выполнив след. команду на сервере:\n\n```bash\nps -ef | grep \"postgresql.*config_file\"\n```\n\nВ случае, если PostgreSQL запущен, в выводе команды вы должны увидеть нечто вроде:\n```bash\n\u003cPG_PATH\u003e -D \u003cDATA_DIR\u003e -c config_file=\u003cCONFIG_PATH\u003e\n```\n\nГде `\u003cPG_PATH\u003e` — путь до исполняемого файла PostgreSQL,\n    `\u003cDATA_DIR\u003e` — путь до директории с данными кластера,\n    `\u003cCONFIG_PATH\u003e` — пусть до конфигурационного файла `postgresql.conf` (потребуется для дальнейшей диагностики).\n\nВ противном случае, проблема найдена: PostgreSQL не запущен.\nПри этом, если попытка запуска СУБД окажется неудачной — в первую очередь обратите внимание на её логи.\n\n#### 2.1.2. Верен ли TCP-порт, открываемый сервером PostgreSQL?\n\nТеперь необходимо убедиться, что PostgreSQL слушает нужный вам TCP-порт (если, конечно, вы не собираетесь работать только через Unix-сокеты).\nОткройте конфигурационный файл `postgresql.conf` (путь до него мы определили этапом выше) и найдите параметр `port`.\nТам должно быть значение необходимого вам порта, который по умолчанию равен `5432`.\nВ противном случае, исправьте номер порта на нужное вам значение. После применения изменений необходимо произвести рестарт PostgreSQL.\n\n_\\* В то же время, можно скорректировать значения порта непосредственно на клиенте (т.е. там, где возникла ошибка соединения)\n— всё зависит от того, какой из портов вы считаете корректным._\n\nПосле рестарта PostgreSQL можно удостовериться, что нужный вам порт действительно прослушивается.\nДля этого можно выполнить след. команду на сервере (для порта `5432`):\n```bash\nss -ln | grep \":5432\"\n```\n\nВ случае успеха, в выводе команды вы должны наблюдать одну или несколько строк с операцией _LISTEN_, которые показывают, что PostgreSQL действительно прослушивает порт.\nВ противном случае (учитывая, что шаг выше показал, что основной процесс СУБД запущен),\nвероятно, вы неверно указали значение `port` либо настроена работа только через Unix-сокеты — как это исправить см. ниже.\n\n#### 2.1.3. Верны ли адреса TCP/IP, по которым PostgreSQL принимает подключения?\n\nПараметром в файле `postgresql.conf`, отвечающим за то, через какие [сетевые интерфейсы](https://ru.wikipedia.org/wiki/%D0%A1%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B9_%D0%B8%D0%BD%D1%82%D0%B5%D1%80%D1%84%D0%B5%D0%B9%D1%81)\nPostgreSQL будет принимать соединения, является `listen_addresses`.\n\nЕсли вы хотите подключиться к PostgreSQL локально (т.е. с того же сервера), подойдут значения\n`127.0.0.1` (для подключения по IPv4), `::1` (для подключения по IPv6) или `localhost` (в современных ОС данное доменное имя, как правило, транслируется в `::1`. Подробнее см. [тут](https://ru.wikipedia.org/wiki/Localhost)).\nСтоит отметить, что в параметре `listen_addresses`, как следует из его названия, можно указать несколько значений через запятую.\nУчтите, что старые клиентские приложения, в подавляющем большинстве случаев, работают по IPv4.\n\nЕсли вы хотите подключиться к PostgreSQL удаленно (т.е. с другого сервера), то необходимо принимать подключения с соотв. внешних интерфейсов.\nС помощью значения `0.0.0.0` можно принимать подключения со всех адресов IPv4, а `::` — все адреса IPv6.\nВ то же время, если указать значение `*`, то PostgreSQL будет принимать подключения со всех имеющихся сетевых интерфейсов.\n\nПодробнее о подключениях и аутентификации к PostgreSQL см. [тут](https://postgrespro.ru/docs/postgresql/17/runtime-config-connection#RUNTIME-CONFIG-CONNECTION-SETTINGS).\nНапомним, что после применения изменений в файл `postgresql.conf` необходимо произвести рестарт PostgreSQL.\n\n:exclamation: В случае, если вы указали PostgreSQL прослушивать внешние интерфейсы\n(т.е., что-то, отличное от значений `127.0.0.1`, `::1` или `localhost` параметра `listen_addresses`),\nто ваш сервер может быть доступне извне (т.е. из Интернета) и потенциально находится под угрозой.\nЧтобы избежать негативных последствий, необходимо корректно настроить ваш [firewall](https://ru.wikipedia.org/wiki/%D0%9C%D0%B5%D0%B6%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B9_%D1%8D%D0%BA%D1%80%D0%B0%D0%BD) и файл `pg_hba.conf`. Подробнее о них см. ниже.\n\n#### 2.1.4. Верна ли конфигурация аутентификации клиентов PostgreSQL?\n\nНесмотря на то, что параметр `listen_addresses` в файле `postgresql.conf` настроен верно, PostgreSQL всё ещё может отвергать соединения.\nПричиной может быть то, что в конфигурационном файле `pg_hba.conf` нет соответствующего разрешения.\n\nПодробнее о файле `pg_hba.conf` см. [тут](https://postgrespro.ru/docs/postgresql/17/auth-pg-hba-conf) (включая примеры настройки).\n\n#### 2.1.5. Верна ли конфигурация firewall? \n\nДаже если PostgreSQL настроен верно (с точки зрения подключения клиентов), вы всё ещё можете иметь неудачные попытки подключения.\nВ этом случае вам необходимо обратить внимание на правильность настройки [firewall](https://en.wikipedia.org/wiki/Firewall_(computing))\n(он может быть как на уровне ОС, так и на уровне ваших сетевых аппаратных/виртуальных устройств, напр., роутера).\nКонкретные шаги выходят за рамки данного FAQ.\n\n---\n\n### \u003ca name='2.2-name-does-not-exist' /\u003e [2.2.](#2.2-name-does-not-exist) Получаю ошибку что имя таблицы/колонки/etc неверное, хотя это не так. В чем дело?\n\nВ подавляющем большинстве случаев, дело в том, что имя таблицы/колонки (равно как и любого другого символьного идентификатора) содержит символы в верхнем регистре (т.е. заглавные буквы).\nВ то же время, по умолчанию, PostgreSQL преобразовывает указанные в запросе/команде идентификаторы в нижний регистр.\nЧтобы избежать ошибки, в запросе/команде необходимо заключить идентификатор в двойные кавычки (в этом случае вышеописанное преобразование будет отключено).\n\nПример воспроизведения и решения проблемы:\n\n```sql\nSELECT * FROM TableName; -- error: relation \"tablename\" does not exist\nSELECT * FROM \"TableName\"; -- OK\n```\n\nОбратите внимание, что идентификатор `TableName` без двойных кавычек был преобразован в `tablename`, что вызвало ошибку.\n\nДля того, чтобы даже гипотетически избежать таких проблем, не рекомендуется использование символов верхнего регистра в идентификаторах.\nОднако, это ни в коем случае не является обязательным правилом.\n\n---\n\n### \u003ca name='2.3-data-publication' /\u003e [2.3.](#2.3-data-publication) Как публиковать SQL запросы, определения функций, выводы команд вспомогательных утилит и прочую текстовую информацию при запросе помощи у сообщества?\n\nПрежде всего, **не используйте** скриншоты для того, чтобы показать SQL запросы (и/или их результаты), определения функций,\nвыводы команд вспомогательных утилит (таких, как [psql](https://postgrespro.ru/docs/postgresql/17/app-psql) и др.) и прочую текстовую информацию — это затрудняет их анализ, скорость/удобство воспроизведения проблемы и переиспользования вашего кода.\nЗаметно эффективнее будет публикация оных, напр., на [gist](https://gist.github.com/) или [pastebin.com](https://pastebin.com/).\n\nПри этом, если вы задаете вопрос в tg-чате и кол-во содержимого невелико, его следует опубликовать в режиме [форматирования Monospace](https://telegra.ph/markdown-07-07) непосредственно в чат, используя ` ```language syntax `, выбрав в кач-ве языка `sql` (таким образом будет достигнута подсветка синтаксиса SQL).\nКак правило, этот вопрос тесно связан с п. [2.4](#2.4-slow-query) и п. [2.5](#2.5-invalid-query).\n\nМногие участники сообщества принципиально не рассматривают скриншоты (и на это есть рациональные причины), поэтому постарайтесь оформить свой текст правильно.\n\n---\n\n### \u003ca name='2.4-slow-query' /\u003e [2.4.](#2.4-slow-query) У меня медленно работает SQL запрос и я хочу попросить помощи у сообщества. Какую информацию мне необходимо предоставить?\n\nЧтобы получить адекватную помощь по оптимизации запроса, необходимо немного постараться и собрать некоторые данные.\u003cbr\u003e\nМинимальная информация для получения помощи следующая:\n\n1. Версия PostgreSQL на сервере, где запускается запрос — можно использовать вывод `SELECT version();`\n2. Непосредственно SQL запрос;\n3. Вывод метакоманды `\\d+` из утилиты [psql](https://postgrespro.ru/docs/postgresql/17/app-psql) для каждой используемой в запросе таблицы;\n4. `EXPLAIN (ANALYZE, VERBOSE, BUFFERS, COSTS, SETTINGS, TIMING, WAL)` для запроса (подробнее об _EXPLAIN_ см. [тут](https://postgrespro.ru/docs/postgresql/17/sql-explain)).\nЕсли ваша версия PostgreSQL ещё не поддерживает какие-то из опций _EXPLAIN_ выше, то уберите их. Когда нет возможности дождаться результата запроса, можно также убрать и опцию _ANALYZE_.\n\n:bulb: Для автоматизации этого процесса можно воспользоваться [данным](https://gist.github.com/hyperion-cs/dc97d41e8e4f44944c876015b61f56c4) _.sql_ скриптом под утилиту `psql`.\n\n:exclamation: Внимательно отнеситесь к тому, как [публиковать информацию](#2.3-data-publication), которая требуется для ответа на ваш вопрос.\n\n---\n\n### \u003ca name='2.5-invalid-query' /\u003e [2.5.](#2.5-invalid-query) У меня не получается написать SQL запрос/etc и/или я получаю ошибки. Какую информацию мне необходимо предоставить для получения помощи от сообщества?\n\n1. Кратко опишите предметную область и то, что вы хотите сделать;\n2. Продемонстрируйте то, что вы уже сделали. Это докажет то, что вы попытались решить проблему самостоятельно,\nа также даст начальную точку для участников сообщества, которые захотят вам помочь. Если вы получаете ошибки, то их также стоит приложить к своему вопросу;\n3. Выполните хотя бы один из пунктов:\u003cbr\u003e\n    3.1. Предоставьте вывод метакоманды `\\d` из утилиты [psql](https://postgrespro.ru/docs/postgresql/17/app-psql) для каждой таблицы, которая будет участвовать в запросе;\u003cbr\u003e\n    3.2. Создайте тестовое окружение, которое воспроизводит ваши [таблицы](https://postgrespro.ru/docs/postgresql/17/ddl)/данные и непосредственно проблему.\n         Это поможет другим участникам сообщества легко и быстро приступить к изучению вашей проблемы (и, как следствие, повысит желание помогать в её решении).\n         Для этого следует использовать такие сервисы как [sqlize.online](https://sqlize.online/) или [db-fiddle.com](https://www.db-fiddle.com/).\u003cbr\u003e\n\n:exclamation: Внимательно отнеситесь к тому, как [публиковать информацию](#2.3-data-publication),\nкоторая требуется для ответа на ваш вопрос.\n\n---\n\n### \u003ca name='2.6-coding-style' /\u003e [2.6.](#2.6-coding-style) В каком стиле писать код и идентификаторы в PostgreSQL?\n\nСтоит отметить, что у сообщества нет единого мнения по данному вопросу.\nОднако, настоятельно не рекомендуется использовать в идентификаторах (именах объектов) что-то, отличное от символов латинского алфавита из нижнего регистра (_a-z_), арабских цифр (_0-9_) и символа нижнего подчеркивания (\\_), т.к. это потенциально может привести к техническим проблемам. В том числе использование символов из верхнего регистра (напр., _A-Z_) имеет нюансы, описанные [ранее](#2.2-name-does-not-exist). Как следует из вышесказанного, символы русского алфавита также не рекомендуются.\n\nВ остальном, это зависит исключительно от того, как принято в вашей команде и/или организации (см. [coding style](https://en.wikipedia.org/wiki/Programming_style)).\nВнутри команды и/или организации важно соблюдать единый стандарт для того чтобы в дальнейшем его было легко читать/поддерживать как вам, так и вашим коллегам.\n\nЕсли обратиться к примерам [официальной документации](https://www.postgresql.org/docs/) PostgreSQL (которые также имеют некоторое разночтение), то, как правило, им свойственно следующее:\n1. Почти все [ключевые слова](https://postgrespro.ru/docs/postgresql/17/sql-keywords-appendix),\nвключая слова из [DML](https://ru.wikipedia.org/wiki/Data_Manipulation_Language) (_SELECT/INSERT/UPDATE/DELETE_), \n[DDL](https://postgrespro.ru/docs/postgresql/17/ddl) (_CREATE/ALTER/DROP_),\n[DCL](https://ru.wikipedia.org/wiki/Data_Control_Language) (_GRANT/REVOKE_),\nа также TCL (_COMMIT/ROLLBACK/SAVEPOINT_) пишутся в верхнем регистре. Исключение составляют идентификаторы (см. ниже). Например:\n    ```sql\n    SELECT * FROM table;\n    ```\n2. Идентификаторы (имена таблиц, столбцов, функций, типов и т.д.) в большинстве случаев пишутся в нижнем регистре в формате [snake_case](https://ru.wikipedia.org/wiki/Snake_case). Например:\n    ```sql\n    SELECT floor(col_name) FROM table;\n    ```\n\n---\n\n### \u003ca name='2.7-partitioning' /\u003e [2.7.](#2.7-partitioning) Секционирование (партиционирование)\n\n#### \u003ca name='2.7.1-partitioning-reasons-for-use' /\u003e [2.7.1.](#2.7.1-partitioning-reasons-for-use) Какие убедительные причины (не)использования секционирования?\n:white_check_mark: Когда это может быть необходимо и/или полезно:\n- PostgreSQL [имеет](https://www.postgresql.org/docs/current/limits.html) некоторые жёсткие ограничения, которые касаются, в частности, и максимального размера отношения (чем является таблица) — `32 TB`. Таким образом, если объем ваших данных в таблице приближается к данному значению, то это веский повод задуматься о секционировании в самое ближайшее время;\n- Если кол-во записей в таблице начинает превышать 5-10 миллиардов строк (и её размер составляет несколько _TB_ без учета индексов — в этом смысле важна средняя ширина строк в таблице), то это повод неспеша задуматься о секционировании;\n- Если появилась необходимость отправлять часть данных таблицы в \"холодное\" (более дешевое, но менее производительное) хранилище/архив — секционирование может помочь. Это разумно в случаях, когда эти данные требуются только в режиме read-only, и сравнительно редко. Как правило, к этому приходят по экономическим причинам (в то же время, производительность системы так или иначе падает).\n\n:x: Когда в этом нет необходимости и/или может быть вредно:\n- Не стоит применять секционирование только потому что это \"модно\", без оглядки на объективные технические причины. Иначе, вполне вероятно, вы получите больше вреда нежели пользы;\n- Если кол-во записей в таблице не превышет 5-10 миллиардов строк (а её размер не превышает несколько _TB_ без учета индексов), то, в среднем, задумываться о секционировании преждевременно — разумнее будет рассмотреть вертикальное масштабирование сервера СУБД, если необходимо. Однако, следует учитывать динамику роста кол-ва данных в таблице с течением времени (соотнося её с предполагаемым временем жизни системы);\n- Если вы планируете применить секционирование, физически оставив/расположив секции на одном накопителе (диске) — в большинстве случаев это сомнительная затея. Бывают и исключения, которые частично описаны в данном FAQ.\n\n#### \u003ca name='2.7.2-partitioning-pros-and-cons' /\u003e [2.7.2.](#2.7.2-partitioning-pros-and-cons) Какие плюсы и минусы есть у секционирования?\n:white_check_mark: Плюсы:\n- Массовое удаление данных можно осуществить удаляя конкретные секции — что значительно эффективнее (в нескольких смыслах), чем аналогичный _DELETE statement_ для обычной таблицы. Очевидно, это возможно лишь в случаях, когда в этих секциях не содержится ничего кроме запланированных к удалению данных;\n- Секции можно расположить на различных [tablespaces](https://www.postgresql.org/docs/current/manage-ag-tablespaces.html) или даже экземплярах PostgreSQL — используя, напр., [foreign data wrappers](https://www.postgresql.org/docs/current/postgres-fdw.html). Это открывает возможности к горизонтальному масштабированию СУБД (впрочем, это не единственный варант).\n\n:x: Минусы:\n- На каждую секцию создается **отдельный** индекс. Это, помимо прочего, может привести к замедлению запросов в `N` раз (где `N` - кол-во секций). Однако, в некоторых случаях может заметно помочь [partition pruning](https://www.postgresql.org/docs/current/ddl-partitioning.html#DDL-PARTITION-PRUNING);\n- Поддерживать секционированную таблицу, так или иначе, сложнее, чем обычную.\n\n#### \u003ca name='2.7.3-partitioning-nuances' /\u003e [2.7.3.](#2.7.3-partitioning-nuances) Какие нюансы есть при работе с секционированием?\nПредставим, что вы всё-таки решили использовать секционирование. В таком случае, вам следует знать следующее:\n- Не следует делать слишком большое кол-во секций (и/или которые содержат слишком мало данных). В первом приближении можно исходить из того, что `10 000` секций — это **верхний** предел, до которого секционирование работает условно-нормально. Это связано с тем, что [планировщик](https://www.postgresql.org/docs/current/planner-optimizer.html) для каждого запроса к секционированной таблице должен решить, какие секции потребуются для работы, что требует времени;\n- Из коробки PostgreSQL поддерживает [декларативное](https://www.postgresql.org/docs/current/ddl-partitioning.html#DDL-PARTITIONING-DECLARATIVE) секционирование и [с использованием наследования](https://www.postgresql.org/docs/current/ddl-partitioning.html#DDL-PARTITIONING-USING-INHERITANCE), первый вариант активно развивается и является хорошей отправной точкой для погружения в данную тему. Однако, существуют и сторонние решения, которые могут помочь в этом с уклоном в горизонтальное масштабирование/шардирование (напр., [citus](https://github.com/citusdata/citus), [spqr](https://github.com/pg-sharding/spqr) и [timescaledb](https://github.com/timescale/timescaledb)).\n\n---\n\n### \u003ca name='2.8-fat-dbms' /\u003e [2.8.](#2.8-fat-dbms) База/таблица весит больше чем я ожидаю, что делать?\nТакое состояние может возникать по разным причинам, и не все случаи требуют вмешательства.\u003cbr\u003e\nРассмотрим некоторые из них:\n- Вы что-то удалили из таблицы посредством [_DELETE_](https://postgrespro.ru/docs/postgresql/17/sql-delete) и ожидаете что на диске появится дополнительное свободное место, либо были обновления через [_UPDATE_](https://postgrespro.ru/docs/postgresql/17/sql-update) и таблица \"распухла\"?\u003cbr\u003e\n  - При удалении строк они физически **не удаляются** с диска, а лишь помечаются как удаленные;\n  - При обновлении строк они физически **не обновляются** \"на месте\", вместо этого создаются новые строки (старые же помечаются как удаленные — в этом смысле _UPDATE_ можно рассматривать как атомарный _DELETE_ + [_INSERT_](https://postgrespro.ru/docs/postgresql/17/sql-insert)). Если не менялся [_primary key_](https://postgrespro.ru/docs/postgresql/17/ddl-constraints#DDL-CONSTRAINTS-PRIMARY-KEYS) (при его наличии), то, логически, это та же самая строка;\n  - Нередко это штатная ситуация, когда свободное место не возвращается ОС — оно будет переиспользовано СУБД в дальнейшем;\n  - Эти процессы могут порождать т.н. _table bloat_ (похожим образом могут распухать и, напр., индексы). Решение этой \"проблемы\" можно начать со знакомства с командой [_VACUUM_](https://postgrespro.ru/docs/postgresql/17/sql-vacuum) (в т.ч. опции _FULL_) и механизма [autovacuum](https://postgrespro.ru/docs/postgresql/17/routine-vacuuming#AUTOVACUUM), но есть и более продвинутые способы.\n\n- Когда-то был сбой в СУБД (в т.ч. неблагоприятный откат транзакции и/или аварийное завершение работы)?\u003cbr\u003e\n  - В этом случае, вероятно, могут появиться т.н. \"файлы-сироты\" (_probably orphaned files_). Они физически есть на диске, однако, уже не связаны логически с БД (т.е., фактически, представляют собой мусор). Вы можете выявить их (и далее, возможно, вручную удалить) с помощью [данного](https://gist.github.com/hyperion-cs/c0df0110e6fc575dc85f797af4342afe) скрипта.\u003cbr\u003e\n  :warning: Иногда вы можете быть и не в курсе, что это произошло. Таким образом, время от времени, отслеживать \"сирот\" не помешает.\n\n### \u003ca name='2.9-timestamptz' /\u003e [2.9.](#2.9-timestamptz) Как работает тип _timestamp with time zone_?\nПрежде всего, в PostgreSQL **нет** встроенного типа данных, который бы хранил временную метку вместе с часовым поясом.\nИ даже `timestamp with time zone` (он же `timestamptz`), несмотря на его название, этой информации не хранит. Однако, это не является проблемой.\u003cbr\u003e\nВ среднем, при _записи_ в БД значения от клиента, оно на уровне СУБД преобразуется к [UTC](https://en.wikipedia.org/wiki/Coordinated_Universal_Time), а при _запросе_ клиентом значения из БД оно преобразуется в локальное время, также на уровне СУБД (в т.ч. к метке добавляется часовой пояс в формате `+TZ` в конце строки — в этом смысле название типа _... with time zone_ себя в некоторой степени оправдывает).\n\nБолее подробно это поведение [описывается](https://postgrespro.ru/docs/postgresql/17/datatype-datetime#DATATYPE-DATETIME-INPUT-TIME-STAMPS) в документации.\n\n:bulb: Приведение на уровне СУБД временной метки к UTC (и из него) для типа `timestamp with time zone` справедливо для случаев, когда клиент и СУБД обмениваются временными метками как строками (в подавляющем большинстве случаев это так, но иногда ответственность за приведение может взять на себя клиент). Как бы то ни было, в любом случае, вышуказанный тип не будет хранить часовой пояс (и СУБД будет полагать, что там физически хранится значение в формате UTC).\n\n:exclamation: Во избежание путаницы, с клиента к СУБД рекомендуется передавать временную метку в виде строки где **явно** указан часовой пояс (по стандарту [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601), т.е. `YYYY-MM-DD HH:MI[:SS][.FFFFFF]+TZ`, где `[:SS]` (_кол-во секунд_) и `[.FFFFFF]` (_\"дробная\" часть секунды_) являются опциональными частями; пример: `2025-01-20 17:14:16.71292+03`). Это гарантирует, что приведение к UTC внутри СУБД будет выполнено корректно вне зависимости от текущей конфигурации локальной временной зоны как на сервере, так и на клиенте.\n\n---\n\n### \u003ca name='2.10-why-asterisk-is-bad' /\u003e [2.10.](#2.10-why-asterisk-is-bad) Что не так со звездочками (*)?\nНе используйте _SELECT/RETURNING *_ кроме как для отладки. Где бы то ни было. Сразу по нескольким причинам, в т.ч.:\n- Производительность — чем больше столбцов возвращает запрос, тем больше нагрузка на сеть, сериализацию данных и т.д. В некоторых случаях может и вовсе быть \"лишний поход\" в [TOAST](https://postgrespro.ru/docs/postgresql/17/storage-toast) за теми данными, которые на самом деле не нужны, что является достаточно дорогой операцией;\n- Безопасность — при добавлении новых, в т.ч. системных/конфедициальных столбцов, в используемые в запросе таблицы, они случайно могут \"протечь\" туда, куда не следует (вплоть до конечного клиента в запущенных случаях);\n- Предсказуемость и стабильность поведения — в общем случае непонятно, что такое \"вернуть всё\", особенно с течением времени (и результаты могут быть довольно неожиданными).\n\nНапример:\n```sql\nSELECT * FROM users; -- Плохо\nSELECT id, name FROM users; -- Хорошо\n```\n\n### \u003ca name='2.11-pgdump_is_not_backup' /\u003e [2.11.](#2.11-pgdump_is_not_backup) Утилита pg_dump создает бэкапы?\n\nОзнакомившись с [документацией](https://www.postgresql.org/docs/17/app-pgdump.html) (и не только) можно предположить, что _pg_dump_ является утилитой для создания бэкапов.\nОднако, в действительности, она создает не полноценный бэкап, а лишь **логический дамп** содержимого базы данных,\nна основании которого в дальнейшем можно попытаться \"восстановить\" состояние БД. Среди прочего:\n- Восстановленные (через [pg_restore](https://postgrespro.ru/docs/postgresql/17/app-pgrestore)) объекты получают другие [OID](https://postgrespro.ru/docs/postgresql/17/datatype-oid);\n- Время восстановления труднопрогнозируемо (в т.ч. при построении индексов) и в среднем _заметно дольше_, чем у подходящих инструментов;\n- В ряде случаев _pg_dump_ может аварийно завершиться или выдать некорректные результаты ([пример](https://t.me/pgsql/479018));\n- Интерфейс утилиты перегружен исторически устаревшими и запутанными параметрами — это может привести к неожиданным результатам.\n\nДля создания надежных бэкапов (бинарных копий) следует использовать, напр., [pg_basebackup](https://postgrespro.ru/docs/postgresql/17/app-pgbasebackup) или иные соотв. утилиты.\n\n## \u003ca name='3-learning' /\u003e [3.](#3-learning) Книги/курсы :blue_book:\n1. [Образовательные материалы](https://postgrespro.ru/education/) от компании Postgres Professional, в т.ч. (в порядке увеличения сложности):\u003cbr\u003e\n    1.1. [Postgres: первое знакомство](https://www.postgrespro.ru/education/books/introbook) (книга, [.pdf](https://edu.postgrespro.ru/introbook_v11.pdf));\u003cbr\u003e\n    1.2. [PostgreSQL. Основы языка SQL](https://postgrespro.ru/education/books/sqlprimer) (книга, [.pdf](https://edu.postgrespro.ru/sql_primer.pdf));\u003cbr\u003e\n    1.3. [PostgreSQL. Профессиональный SQL](https://postgrespro.ru/education/books/advancedsql) (книга, [.pdf](https://edu.postgrespro.ru/advanced_sql.pdf));\u003cbr\u003e\n    1.4. [Основы технологий баз данных](https://postgrespro.ru/education/university/dbtech);\u003cbr\u003e\n    1.5. [PostgreSQL изнутри](https://www.postgrespro.ru/education/books/internals) (книга, [.pdf](https://edu.postgrespro.ru/postgresql_internals-17.pdf)).\n\n_* Стоит заметить, что материалы выше не являются рекламой — они действительно крайне достойного качества, при этом распространяются свободно._\n\n## \u003ca name='4-links' /\u003e [4.](#4-links) Полезные ссылки :link:\n\n1. [Документация PostgreSQL на русском языке](https://postgrespro.ru/docs/postgresql/);\n2. [Вредные и/или опасные действия в PostgreSQL](https://wiki.postgresql.org/wiki/Don't_Do_This) _(eng)_;\n3. [SQLize — быстрый запуск, эксперименты и обмен кодом SQL](https://sqlize.online/);\n4. [SQLtest — упражнения по SQL](https://sqltest.online/ru);\n5. LeetCode Database Problems — упражнения по SQL: [базовые задачи](https://leetcode.com/studyplan/top-sql-50/), [все задачи](https://leetcode.com/problem-list/database/) _(eng)_;\n6. [Sql-ex.ru — упражнения по SQL](https://www.sql-ex.ru/?Lang=0);\n7. [Официальный FAQ на русском языке](https://wiki.postgresql.org/wiki/FAQ/ru);\n8. [Neon — туториалы по PostgreSQL, примеры использования](https://neon.tech/postgresql/tutorial) _(eng)_;\n9. [pgPedia — энциклопедия PostgreSQL](https://pgpedia.info/) _(eng)_;\n10. [postgresqlco.nf — описание и управление конфигурацией](https://postgresqlco.nf/) _(eng)_.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhyperion-cs%2Fpgsql_faq","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhyperion-cs%2Fpgsql_faq","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhyperion-cs%2Fpgsql_faq/lists"}