Ценность Соответствующего Комментария

У каждого из нас есть задача, над которой вы долго и безуспешно бьетесь, которую уже изучили вдоль и поперёк, но до сих пор не можете получить желаемый результат. При этом одни уверены, что ваша проблема в принципе не имеет решения, другие – что проблемы вообще нет. Для меня этой проблемой было время, необходимое для выполнения запросов к хранилищу данных Greenplum. И как приятно наконец написать, что я поборола эту проблему!

Ценность соответствующего комментария

Когда пытаешься понять, почему запросы выполняются так долго Раз за разом при работе с репозиторием ожидание результата запроса занимало несколько минут. И не важно, будет ли запрос выбирать данные из таблицы на десять строк или на миллион — время ожидания будет сопоставимым.

А любой простой в таком творческом процессе, как аналитика, – это просто пытка! Я много раз пытался исправить это поведение.

Я начал с настройки клиента sql. DBeaver предлагает пользователям целый ряд различных вариантов тонкой настройки — думаю, я опробовал их все безуспешно.

Далее я попробовал настройки самого драйвера PostgreSQL — эффект был тот же.

Все это время перед моими глазами был пример специализированного клиента для Greenplum — Aginity Workbench, в котором из коробки скорость выполнения подобных запросов существенно выше.

Эта программа была дополнительным раздражающим фактором, так как причин такого ускорения я найти не смог - ее исходный код закрыт и она работает только под лицензией, а подключение к greenplum в ней происходит родными средствами, а не штатными jdbc-драйверами.

.

Вдохновение пришло, когда я заглянул в системное представление pg_ стат_ активности — оказалось, что на самом деле от клиента в базу данных летит не один запрос данных, а два: сначала происходит выборка данных по запросу, а затем метаданные для этой выборки считываются из pg_ каталог.

При этом из общего времени выполнения наибольшую часть занимает чтение метаданных.



Ценность соответствующего комментария

В этот момент я испытал целую бурю эмоций – от радости, что наконец-то нашел проблему, до недоумения по поводу самой сути открытия.

Я и раньше знал, что каталог изрядно загружен: сейчас к хранилищу подключено более 250 исходных систем, каждая с сотней таблиц, а сами таблицы могут иметь двухуровневую партиционацию.

Greenplum рассматривает каждый раздел как отдельный объект, поэтому системные представления, такие как pg_class, становятся сильно раздутыми.

Но действительно ли необходим доступ к каталогу для любого запроса данных? К счастью, драйвер Postgres имеет открытый исходный код. источник , чтобы вы могли сами увидеть, что происходит под капотом.

Я заглянул в код и нашел нужный класс.

Пгрезультатсетметадата и его метод, запрашивающий метаданные, — fetchFieldMetaData. Содержание обнадёживает - вроде можно обойтись и без метаданных: fetchFieldMetaData вызывается из нескольких других методов, которые для моих целей не столь важны, а сами эти методы позволяют вернуть пустой объект, что намекает на возможность вырезания исключить все вызовы fetchFieldMetaData из кода, что означает отсутствие медленных запросов к каталогу.

Подробнее о методах:

  • isAutoIncrement. В этом методе проще всего избегать запроса метаданных: в нашем репозитории таких полей нет, а комментарий «Считается, что PostgreSQL не поддерживает эту возможность» как бы намекает, что для других баз данных она не будет полезна.

      
      
      
       

    public boolean isAutoIncrement(int column) throws SQLException { fetchFieldMetaData(); Field field = getField(column); FieldMetadata metadata = field.getMetadata(); return metadata != null && metadata.autoIncrement; }

  • isNullable. Если в наборе результатов нет метаданных, все поля будут считаться обнуляемыми — без больших потерь.



    public int isNullable(int column) throws SQLException { fetchFieldMetaData(); Field field = getField(column); FieldMetadata metadata = field.getMetadata(); return metadata == null ? ResultSetMetaData.columnNullable : metadata.nullable; }

  • getBaseColumnName. В коде драйвера этот метод используется в обновляемых наборах результатов при обновлении значений.

    В мои планы не входит использование этого функционала, но на всякий случай можно будет добавить исключения при вызове таких методов.



    public String getBaseColumnName(int column) throws SQLException { Field field = getField(column); if (field.getTableOid() == 0) { return ""; } fetchFieldMetaData(); FieldMetadata metadata = field.getMetadata(); return metadata == null ? "" : metadata.columnName; }

  • getBaseSchemaName и getBaseTableName. Возвращает имя схемы/таблицы, в которой находится запрошенный атрибут. Этот метод нигде в коде драйвера не используется; Мне эта информация тоже не особо нужна.



    public String getBaseSchemaName(int column) throws SQLException { fetchFieldMetaData(); Field field = getField(column); FieldMetadata metadata = field.getMetadata(); return metadata == null ? "" : metadata.schemaName; } public String getBaseTableName(int column) throws SQLException { fetchFieldMetaData(); Field field = getField(column); FieldMetadata metadata = field.getMetadata(); return metadata == null ? "" : metadata.tableName; }

Проверяю влияние по коду, закомментирую вызов метода fetchFieldMetaData, собираю jar-файл драйвера, подключаюсь с его помощью к базе данных, иииии.

Сказать, что это дало результат, значит ничего не сказать.

Запросы сейчас просто летят. Ускорение - во много раз.

Отправил коллегам на пробу — отзывы были примерно такие:

Ценность соответствующего комментария

Дополнительный бонус, который греет сердце: исключив ненужные запросы метаданных к каталогу pgclass, мы снимаем с него лишнюю нагрузку.

Не уверен, что это имеет какой-то существенный эффект для хранилища, но здесь, как и в борьбе за экологию, даже отрадно, что вы хоть несколько улучшаете ситуацию.

В общем, не опускайте руки, если проблема сохраняется долгое время – вполне вероятно, что ответ где-то рядом и какая-то мелочь отделяет вас от успеха.

В моем случае такой мелочью были символы комментариев, которые нужно было разместить в нужных местах.

P.S. В финальной версии кода я создал новый параметр подключения драйвера runtimeMetaDisable. Вызов метаданных и выдача исключений привязаны к их значению.

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

Код был опубликован на github .

Если ваша база данных имеет тяжёлый каталог и вы хотите попробовать драйвер в действии, но не знакомы с миром java и не знаете, как собрать jar-файл драйвера, пишите в комментариях! Теги: #greenplum #postgres #sql #управление данными в ростелекоме #Jdbc #driver

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.