RSS Telegram YouTube Apple Яндекс Spotify Amazon Почта

68. auto_explain, ClickHouse, import cycle in Go

07.09.2024

Скачать

К списку выпусков

Ссылки выпуска:

Отсутствие циклических зависимостей в коде - это хорошо

На этой неделе мне довелось делать обширный рефакторинг в проекте, написанном на Go. После нескольких часов написания кода я запустил тесты и получил ошибку: import cycle not allowed.

Такую ошибку мы получаем в Go, если пакет A использует код из пакета B, а, в свою очередь, пакет B импортирует пакет A. Говоря просто, A и B как-то очень тесно зависят друг от друга. И так как в Go такая ситуация недопустима, то первая идея - объединить пакеты A и B в один, т.е. перенести код из B в A или наоборот. Другое решение - выделить общий код в пакет C, который будут импортировать как A, так и B. В моем случае я объединил оба пакета и, признаюсь, код стал сильно проще.

Почему в Go запрещены циклические зависимости? Для того чтобы это понять нужно смоделировать ошибку циклической инициализации:

// Available at: https://play.golang.com/p/nOlfgNEhdCi
package main

var A int = B
var B int = A

func main() {}

// Compile error message:
// ./prog.go:3:5: initialization cycle for A
// 	./prog.go:3:5: A refers to
// 	./prog.go:4:5: B refers to
// 	./prog.go:3:5: A

Как в случае кода выше присвоить начальное значение переменной A или B? Это невозможно. Отследить такие циклические инициализации в рамках одного пакета несложно, но дольше и ресурснее в пределах нескольких пакетов. Для такого отслеживания понадобился бы анализ исходного кода всех этих пакетов, что осложняет инкрементную компиляцию.

Инкрементная компиляция позволяет собирать только те пакеты Go-проекта, которые перетерпели изменения. Вносим правки в пакет A, только он и компилируется. Это почти всегда так. За счет этого получаем быструю компиляцию. Теперь представим, что нужно проанализировать код всех пакетов и убедиться, что нет циклических инициализаций. Отказ же от циклических зависимостей делает такой анализ ненужным и, соответственно, скорость компиляции проекта высокой.

Пакет в Go - это единица компиляции (compilation unit).

А как в других языках программирования? В Rust, например, циклические зависимости модулей разрешены (модули - аналог пакетов в Go), но они же запрещены на более высоком уровне, на уровне крейтов (крейт - аналог модуля в Go).

auto_explain — log execution plans of slow queries

Начиная с 12 версии PostgreSQL, из коробки, можно включить модуль auto_explain. Этот модуль логгирует (в stderr, stdout, файл и т.д. - зависит от настроек логов в вашем инстанесе PostgreSQL) план выполнения запросов, выполняющихся более auto_explain.log_min_duration мс. Логгировать можно в JSON, YAML, текстовом форматах. В лог попадет расшифровка плана выполнения запроса как если бы вы сделали EXPLAIN для медленного запроса. Конфигурация модуля позволяет настраивать параметры EXPLAIN: ANALYZE, включение таймингов, буферов и т.д.

Unpacking the Buzz around ClickHouse

Для каких задач предпочесть ClickHouse? Для начала немного про OLAP (Online Analytical Processing). Такие аналитические базы данных оптимизированы под выполнение запросов с агрегатными (те, которые возвращают одно значение для набора значений) функциям, например, AVG, SUM, COUNT и т.д. На сайте бенчмарков видно, что для подобных выборок с агрегатными функциями и группировками PostgreSQL работает в 700 раз медленнее, а MySQL в 2000 раз медленнее. Для чего же нужны такие запросы?