Как я сделал легкий инструмент SQL-подсветки без тяжелых зависимостей
Однажды я понял, что подсветка SQL в обучающих проектах — это тот еще квест.
В sqltest.online я использовал highlight.js для подсветки SQL в учебных заданиях.
Либо библиотека тащит за собой лишнее, либо нормально подсвечивает только учебный SQL в духе `SELECT * FROM table`, а как дело доходит до диалектов, функций и более живых запросов, начинается боль.
Я сначала пробовал готовые решения. Потом пытался допиливать описание SQL для highlight.js. В какой-то момент стало понятно: проще собрать свой инструмент под эту задачу, чем дальше воевать с универсальными решениями.
Так появился **sql-highlighter** — легкий JavaScript-хайлайтер для SQL, который:
не тянет тяжелые зависимости,
работает прямо в браузере,
поддерживает light/dark темы,
умеет расширяться под конкретный диалект без правок ядра.
Как это устроено:
Сначала строки и комментарии временно выносятся в отдельные плейсхолдеры.
Потом проходят основные токены: ключевые слова, функции, типы и т.д.
Затем возвращаются строки и комментарии.
Важный момент: порядок обработки имеет значение, чтобы не ломать конструкции вроде `GROUP BY` или `SELECT DISTINCT`.
Самое приятное — можно добавить свои ключевые слова и функции через `SQLHighlighter.extend(...)`, не лезя внутрь библиотеки. Это удобно, если у вас обучающий проект, документация или свой SQL-диалект.
Если коротко: я делал не универсальный SQL-парсер на все случаи жизни, а практичный и быстрый инструмент для реальных веб-проектов, где важны размер, простота и нормальная подсветка.
Если вам нужен SQL-highlighter для сайта, документации или обучения, вот репозиторий проекта: sql-highlighter
Нагрузочное тестирование: зачем оно нужно и как быстро сгенерировать миллионы записей в Oracle
Когда мы разрабатываем систему, чаще всего тестируем её на небольшом объёме данных: несколько десятков или сотен записей. Но в реальной эксплуатации база может содержать миллионы строк, а одновременно системой могут пользоваться тысячи пользователей.
Именно поэтому перед вводом системы в эксплуатацию проводят нагрузочное тестирование.
В канале Аналитика FM я публикую реальные запросы SQL с разбором логики. Обсуждаем продуктовые метрики и как правильно строить аналитику данных.
Канал веду с нуля подписчиков.
Подписывайся, если тоже хочешь вникнуть в прекрасный мир аналитики.
Нагрузочное тестирование - это проверка работы системы под нагрузкой, максимально приближенной к реальной.
Его цель - ответить на вопросы:
Сколько пользователей одновременно выдержит система?
Как быстро будут выполняться запросы?
Как изменится производительность при увеличении объёма данных?
Не начнёт ли база данных работать значительно медленнее?
Не возникнут ли ошибки из-за нехватки памяти, места во временном табличном пространстве или перегрузки процессора?
Например, запрос, который за 0,1 секунды обрабатывает 100 строк, может выполняться несколько минут при таблице в 100 миллионов записей.
Поэтому проверять производительность необходимо именно на объёмах, близких к реальным.
Какие бывают виды нагрузочного тестирования?
1. Load Testing (нагрузочное тестирование)
Проверяется работа системы при обычной ожидаемой нагрузке.
Например:
одновременно работают 500 пользователей;
таблица содержит 10 миллионов записей.
2. Stress Testing (стресс-тестирование)
На систему специально подают нагрузку выше расчётной.
Цель - определить предел её возможностей и понять, как она поведёт себя при перегрузке.
3. Volume Testing (тестирование объёма данных)
Проверяется влияние количества данных на производительность.
Например:
запрос работает с таблицей из 100 тыс. строк;
затем с 10 млн;
затем со 100 млн.
4. Endurance Testing (тестирование на длительную работу)
Система работает под постоянной нагрузкой несколько часов или даже суток.
Проверяют, не возникает ли утечек памяти и деградации производительности.
Как подготовить данные для нагрузочного тестирования Oracle?
Самый простой способ - сгенерировать тестовые записи прямо средствами Oracle.
Например:
SELECT 'ООО Ромашка ' || LEVEL AS name,
7700000000 + LEVEL AS inn,
1027700000000 + LEVEL AS ogrn
FROM dual
CONNECT BY LEVEL <= 1000000;
Этот запрос создаст 1 миллион строк без использования каких-либо таблиц.
И так вы сможете подготовить базу с наполненными данными для тестирования нагрузки.
Иногда такого подхода не хватает, и данные должны быть консистентными, иметь логическую зависимость от других параметров. Но это уже более глубокая семантика нагрузочного тестирования.
А мы с вами начинаем познавать увлекательный мир аналитики и данных.
Разбор скрипта проведем в канале Аналитика FM.
Подписывайся, чтобы узнавать техническую сторону работы аналитика.
Телевизоры вместо картин: Hisense показал в Москве новую линейку
Главной премьерой вечера стал огромный 116-дюймовый телевизор Hisense 116UX. Удивляли гостей не только размеры экрана — компания решила отказаться от привычной презентации.
Технологии на языке искусства
Новую линейку телевизоров компания представила в формате арт-галереи. Вместо привычных стендов — тематические инсталляции, вместо списка характеристик — пространство, где технологии можно увидеть и услышать.
Все это — чтобы показать, насколько яркими и живыми могут быть цвета, как выглядит глубокий черный и на что способна встроенная акустика. Над экранами разместили большие художественные полотна, которые продолжали происходящее на дисплеях.
Новые модели от Hisense
На презентации продемонстрировали несколько моделей новой линейки — UR8S, UR9S и флагманский Hisense 116UX.
Особенность новинок — технология RGB MiniLED. Теперь телевизор точнее управляет цветом и светом, поэтому изображение выглядит ярче, контрастнее и естественнее.
Менеджер по продуктам ТВ- и аудиокатегории Hisense Шон Ли:
«Запуск технологии RGB Mini-LED на российском рынке является новым этапом в развитии Hisense. Мы задали новый стандарт визуального опыта, который уже получил признание на глобальном уровне».
Больше всего внимания собрал Hisense 116UX. Это телевизор с трехметровой диагональю. На таком экране особенно хорошо заметны детали: яркие сцены остаются насыщенными, темные — глубокими, а изображение выглядит объемным и живым. За качество картинки отвечает фирменный процессор Hisense, а встроенная многоканальная акустика создает эффект домашнего кинотеатра без дополнительных колонок.
Вместо лекций — живое общение
Для любителей игр организовали отдельную зону. К телевизорам подключили консоли, чтобы гости могли проверить, как новинки ведут себя в динамике.
Организаторы отказались и от длинных технических презентаций. Гости переходили между зонами, сравнивали модели, задавали вопросы специалистам и тестировали телевизоры в удобном для себя темпе.
Линейка уже поступила в продажу. Доступны модели UR8S в нескольких размерах экрана, серия UR9S и флагманский 116UX. Телевизоры можно приобрести у крупных российских ритейлеров и на популярных маркетплейсах.
Иерархический справочник: когда данные растут как дерево
Представьте дерево. У него есть корень, от него отходят ветки, от больших веток - более мелкие, а затем листья.
Примерно так же устроены иерархические справочники в информационных системах.
И как же можно понять: что есть ветка, а что есть лист в этом иерархическом справочнике?
В канале Аналитика FM я часто разбираю такие ситуации - когда задача вроде решаема, но без нормальной структуры превращается в кашу.
Например:
📁 Транспорт
├── Легковой транспорт
│ ├── Седаны
│ └── Кроссоверы
└── Грузовой транспорт
├── Малотоннажный
└── Тягачи
Или:
📁 Товары
├── Электроника
│ ├── Телефоны
│ └── Ноутбуки
└── Бытовая техника
├── Холодильники
└── Стиральные машины
А как такое дерево хранится в базе данных?
На самом деле всё гораздо проще, чем кажется.
Обычно таблица справочника выглядит примерно так:
| id | name | parent_id |
| --- | ----------------------------------- | --------------- |
| 1 | Транспорт | NULL |
| 2 | Легковой транспорт | 1 |
| 3 | Грузовой транспорт | 1 |
| 4 | Седаны | 2 |
| 5 | Кроссоверы | 2 |
| 6 | Тягачи | 3 |
Структурно это выглядит так:
1 Транспорт
├── 2 Легковой транспорт
│ ├── 4 Седаны
│ └── 5 Кроссоверы
└── 3 Грузовой транспорт
└── 6 Тягачи
Каждая запись имеет:
id - собственный идентификатор;
parent_id - идентификатор родительского элемента.
Например:
id = 4
name = Седаны
parent_id = 2
Это означает:
Седаны → Легковой транспорт → Транспорт
Именно благодаря полю parent_id база понимает, что "Седаны" и "Кроссоверы" относятся к одной ветке дерева.
Если подниматься по родителям вверх, то рано или поздно мы придём к общему узлу - корню ветки.
Получается, что вся иерархия строится буквально на одном поле: parent_id
Для чего нужны иерархические справочники?
Они позволяют хранить данные не просто списком, а показывать связи между объектами.
Благодаря этому можно:
✅ группировать данные;
✅ строить отчёты по категориям;
✅ наследовать свойства от родительских узлов;
✅ задавать правила сразу для целой ветки;
✅ быстро находить все дочерние элементы.
Например, если правило применяется ко всей категории "Легковой транспорт", то оно автоматически действует и для седанов, и для кроссоверов, и для любых новых подкатегорий, которые появятся позже.
Где используются?
📌 MDM-системы (Master Data Management);
📌 каталоги товаров интернет-магазинов;
📌 банковские и страховые системы;
📌 ERP и CRM;
📌 классификаторы услуг и продуктов;
📌 организационная структура компании;
📌 государственные классификаторы и справочники.
Преимущества
✔ Гибкость. Можно добавлять новые ветки без изменения структуры данных.
✔ Удобная аналитика. Легко получить данные как по конкретному элементу, так и по всей категории.
✔ Наследование правил. Одно правило может применяться сразу к тысячам объектов.
✔ Масштабируемость. Структура может содержать десятки и сотни уровней вложенности.
Недостатки
❌ Сложность запросов. Иногда, чтобы найти всех потомков или родителей, приходится строить рекурсивные запросы.
❌ Производительность. Глубокие иерархии могут существенно замедлять выполнение запросов.
❌ Риск циклических ссылок. Если по ошибке сделать узел потомком самого себя, можно получить бесконечный цикл.
❌ Сложность сопровождения. Изменение структуры верхних уровней может затронуть большое количество дочерних элементов.
Как с ними работать?
При работе с иерархическими справочниками чаще всего приходится решать четыре задачи:
🔹 найти всех потомков узла;
🔹 найти всех родителей элемента;
🔹 определить, принадлежит ли элемент определённой ветке;
🔹 определить, к какому верхнему узлу относится конкретный элемент.
В Oracle для этого используются специальные иерархические запросы:
START WITH ...
CONNECT BY ...
Именно они позволяют "обходить дерево" вверх или вниз по веткам.
В канале Аналитика FM (клик :-) ) уже готов пост про конструкцию START WITH и CONNECT BY.
Подписывайся, если интересно разбираться в особенностях работы аналитика.
Иерархический справочник - это не просто список значений. Это способ описать реальные взаимосвязи между объектами и сделать систему более гибкой и управляемой.
А одна маленькая колонка parent_id превращает обычную таблицу в целое дерево данных.
Нас уже больше 9000 на sqltest.online
Нас уже больше 9000 на sqltest.online
Небольшая, но очень приятная новость: на sqltest.online зарегистрировалось уже больше 9000 пользователей.
Когда запускал проект, хотел сделать простую площадку, где можно бесплатно тренировать SQL на реальных СУБД, а не только читать теорию. Сейчас там уже тысячи людей, которые регулярно практикуются, решают задачи и прокачивают запросы.
Для меня это сильная мотивация развивать сервис дальше:
- добавлять новые задания;
- расширять уроки;
- улучшать стабильность и скорость платформы.
Спасибо всем, кто пользуется, пишет фидбек и делится проектом. Без вас этой цифры бы не было.
Если давно хотели подтянуть SQL, можно начать с простого: sqltest.online
Буду рад идеям, какие темы и форматы добавить следующими.
P.S. Для пользователей из РФ работает российское зеркало: sqltest-online.ru
P.S.S. Если вам нравятся мои сервисы, буду рад донату.
Временные таблицы в базе данных
Если ты когда-нибудь писал длинный SQL-запрос и в какой-то момент ловил себя на мысли:
"Я уже сам не понимаю, что здесь происходит" - поздравляю, ты подошёл к моменту, где появляются временные таблицы.
В канале Аналитика FM я часто разбираю такие ситуации - когда задача вроде решаема, но без нормальной структуры превращается в кашу.
Что такое временная таблица
Это обычная таблица…
только с одним отличием:
👉 она живёт временно и потом исчезает
Ты создаёшь её:
чтобы сохранить промежуточный результат
поработать с ним
и не засорять основную базу
Тебе нужно:
взять заказы
отфильтровать только оплаченные
посчитать выручку
добавить сегментацию пользователей
ещё пару условий сверху
Можно написать один огромный запрос.
А можно сделать по-другому:
Сначала собрать "чистые заказы"
Потом на их основе считать метрики
Потом добавлять бизнес-логику
И вот тут временные таблицы начинают играть.
Как это выглядит
CREATE TEMP TABLE temp_orders AS
SELECT *
FROM orders
WHERE status = 'paid';
Создаем промежуточный слой данных.
А потом работаем уже с ним.
SELECT user_id, SUM(amount)
FROM temp_orders
GROUP BY user_id;
Зачем это нужно
1️⃣ Разделить сложную логику
Вместо одного "монстра":
ты разбиваешь задачу на шаги
каждый шаг понятен
легче дебажить
2️⃣ Переиспользовать результат
Если один и тот же кусок данных нужен несколько раз:
не нужно каждый раз пересчитывать
можно сохранить и использовать
3️⃣ Ускорить запросы
Иногда:
тяжёлый JOIN
сложная фильтрация
👉 выгодно посчитать один раз и сохранить результат
4️⃣ Не засорять базу
Если ты создашь обычную таблицу:
она останется
её надо потом удалять
она может мешать другим
Временная таблица:
живёт в рамках сессии
автоматически исчезает
Когда это особенно полезно
сложные аналитические расчёты
многоступенчатые преобразования данных
работа с "грязными" данными
отладка логики
Важный нюанс
Временные таблицы - это не единственный инструмент.
Есть ещё:
CTE (WITH)
подзапросы
Но:
👉 CTE - это "логика в одном запросе"
👉 временные таблицы - это "разбивка на реальные шаги"
Иногда CTE читается тяжело.
А временные таблицы дают ощущение "пайплайна".
Где часто ошибаются
создают временные таблицы без необходимости
забывают, что они завязаны на сессию
используют их там, где проще CTE
То есть это инструмент - не серебряная пуля.
Самая простая мысль
Временная таблица - это способ остановиться посередине запроса и зафиксировать результат
И иногда именно это спасает:
читаемость
производительность
и твои нервы
В канале Аналитика FM (клик :-) )я рассказываю про продуктовые метрики в разных бизнесах. В чем особенности и нюансы. Серия постов про средний чек уже готова.
Подписывайся, если интересно интересно разбираться в особенностях работы аналитика.
Важное обновление: Запуск зеркала sqltest-online.ru
Я знаю, что в последнее время многие пользователи из России столкнулись с трудностями при доступе к основному сайту sqltest.online из-за ограничений регуляторов.
Моя миссия остается прежней: сделать обучение SQL доступным и качественным для каждого. Я убежден, что знания не должны иметь границ, поэтому я подготовил официальное зеркало для бесперебойной работы:
Что важно знать:
Полный функционал: Это точная копия основного ресурса со всеми задачами и тренажерами.
Поддержка пользователей: Я поддерживаю всех учеников по всему миру. Неважно, где вы находитесь — ваша цель выучить SQL приоритетна для меня.
Доступность: Зеркало настроено специально для стабильной работы внутри РФ.
Учитесь, практикуйтесь и повышайте свои навыки без преград. Добро пожаловать! 🎓
Изменения во времени
Представь обычную ситуацию:
Есть клиент, сегодня он живет в Москве
| user_id | city |
| ----------- | ------------- |
| 1 | Москва |
Проходит время, он переезжает в Санкт-Петербург
Ты обновляешь данные
| user_id | city |
| ----------- | ---------------------------- |
| 1 | Санкт-Петербург|
И вроде всё ок.
Но потом приходит задача:
👉 А посчитай выручку по городам за прошлый год
И тут начинается самое интересное.
А в моем канале Аналитика FM выпуски про расчет Cohort Retention в разных бизнесах.
Канал я веду с нуля подписчиков, рассказываю про аналитику и разбираю различные кейсы на реальных примерах.
Подписывайся, если интересно как устроен мир аналитика!
Если ты просто возьмешь текущие данные, то все заказы пользователя "уедут " в Санкт-Петербург. Даже те, которые он делал, когда жил в Москве.
И аналитика начнёт врать.
Не потому что ты ошибся.
А потому что данные потеряли свою историю.
Вот здесь и появляется SCD
SCD (Slowly Changing Dimension) - это способ хранить изменения так,
чтобы ты мог ответить не только на вопрос:
👉 Как сейчас?
но и на более важный:
👉 Как было в момент события?
Как будет выглядеть: вместо одной строки в таблице будет:
| user_id | city | start_date | end_date |
| ------------ | --------------------------- | ----------------- | -------------------- |
| 1 | Москва | 2024-01-01 | 2025-01-01 |
| 1 | Санкт-Петербург| 2025-01-01 | NULL |
Теперь у нас есть не просто данные,
а контекст во времени.
Почему это важно
Потому что почти всё в бизнесе меняется:
клиенты переходят между сегментами
продукты меняют категории
условия договоров обновляются
статусы живут своей жизнью
И если ты смотришь только на "сейчас" - ты теряешь половину смысла.
Самый важный момент
SCD - это не про таблицы.
Это про мышление.
Когда ты начинаешь задавать вопросы так:
А на момент события это было актуально?
А не поменялось ли это потом?
- ты переходишь на другой уровень понимания данных.
Где чаще всего ошибаются
Берут текущие данные
и применяют их к прошлым событиям.
И получается:
красивые отчёты
аккуратные цифры
полностью неверные выводы
Простая мысль, которую стоит запомнить
Данные без времени - это половина правды
SCD - это как раз про то, чтобы эту вторую половину не потерять.
И если тебе интересно разбираться в таких вещах глубже -
не просто "как написать SELECT", а как думать про данные,
в Аналитика FM я как раз про это и пишу.









