TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.75K subscribers
Post #3157 1.91K
День 2632. #МоиИнструменты #PG
Инструменты Оптимизации Запросов в PostgreSQL. Часть 6


6. SQLFluff (SQL-линтер для производительности)
Что даёт: выявляет антипаттерны производительности до того, как запросы попадут в прод.
Зачем нужен: Большинство проблем с производительностью SQL возникают из-за распространённых ошибок: SELECT *, ненужные DISTINCT, отсутствие WHERE, неэффективные соединения. SQLFluff выявляет их на этапе разработки, до того, как они вызовут проблемы в продакшене.
Установка:
pip install sqlfluff

# Создаём конфиг
cat > .sqlfluff <<EOF
[sqlfluff]
dialect = postgres
templater = dbt
[sqlfluff:rules:L042]
# Запрет SELECT * в проде
select_
_targets = qualified
[sqlfluff:rules:L045]
# Обязательные алиасы полей
aliasing = explicit
[sqlfluff:rules:L052]
# Требование явных объединений
join_types = explicit
EOF


Использование
1. Линтинг SQL-файлов:
sqlfluff lint models/*.sql

Пример вывода:
== [models/orders.sql] FAIL
L: 5 | P: 8 | L042 | SELECT * is not allowed in production.
L: 12 | P: 15 | L031 | Avoid DISTINCT where possible (use GROUP BY).
L: 18 | P: 1 | L044 | Query is missing WHERE clause (full table scan).
L: 23 | P: 22 | L052 | JOIN should specify type (INNER, LEFT, etc.).


2. Автоматические исправления:
sqlfluff fix models/*.sql

До SQLFluff:
SELECT * FROM orders o
JOIN customers c ON o.customer_id = c.id
WHERE order_date > '2024-01-01';

Проблемы:
1. SELECT * (возвращает ненужные поля);
2. Неявное объединение (неясное намерение);
3. Сравнение даты без явного приведения типа.

После SQLFluff:
SELECT 
o.order_id,
o.order_date,
o.total,
c.customer_name
FROM orders AS o
INNER JOIN customers AS c
ON o.customer_id = c.id
WHERE o.order_date > CAST('2024-01-01' AS DATE);


Когда использовать
- dbt-проекты (отлично интегрируется);
- Несколько инженеров, пишущих SQL-запросы (обеспечение согласованности);
- Предотвращение распространённых ошибок;
- Конвейер CI/CD для SQL.

Когда отказаться
- Разработчик-одиночка (меньшая ценность);
- ad-hoc запросы (избыточно);
- Нестандартный диалект SQL (ограниченная поддержка).

Скрытая функция
Пользовательские правила для антипаттернов в вашей команде:
# custom_rules/no_cross_joins.py
from sqlfluff.core.rules import BaseRule, LintResult
class Rule_Custom_NoCrossJoin(BaseRule):
"""Запрет CROSS JOIN (почти всегда необязательны)."""

def _eval(self, segment, **kwargs):
if segment.is_type("join_clause"):
if "CROSS" in segment.raw_upper:
return LintResult(
anchor=segment,
description="Найден CROSS JOIN. Почти всегда необязателен.",
fixes=[...] # Опционально: предложение исправления
)

Добавить в .sqlfluff.

С осторожностью
Слишком агрессивный линтинг убивает продуктивность:
# Слишком строго (инженеры возненавидят)
sqlfluff lint --rules all
# Лучше начать с критических правил
sqlfluff lint --rules L042,L044,L052

Постепенно добавляйте правила со временем. Соблюдайте баланс между отловом проблем и сопротивлением разработчиков.

Источник: https://medium.com/@reliabledataengineering/15-sql-optimization-tools-that-make-queries-10x-faster-8629ac451d97
  • 👍 4
More from @netdeveloperdiary
  1. Sep 27, 2026День 2797. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Окончание Начало Продол…
  2. Sep 26, 2026День 2796. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Продолжение Начало Три…
  3. Sep 25, 2026День 2795. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Начало Проблема с позиц…
  4. Sep 24, 2026День 2794. #Оффтоп #Здоровье Сегодня будет необычный пост. Завтра в Москве стартует конфер…
  5. Sep 23, 2026День 2793. #ЗаметкиНаПолях #SQL 10 Редких Возможностей SQL, Которые Стоит Знать Каждому. Ч…
  6. Sep 22, 2026День 2792. #ЗаметкиНаПолях #SQL 10 Редких Возможностей SQL, Которые Стоит Знать Каждому. Ч…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →