Smart Data
Канал про Data Engineering, аналитику и данные. По всем вопросам: @ds_im
Ko'proq ko'rsatish- Kanalning o'sishi
- Post qamrovi
- ER - jalb qilish nisbati
Ma'lumot yuklanmoqda...
Ma'lumot yuklanmoqda...
EXPLAIN SELECT * FROM retail.orders_fact;Запрос вернёт нам результат следующего вида:
Seq Scan on orders_fact (cost=0.00..195.86 rows=9186 width=55)Как мы видим, наш план выполнения запроса состоит из 1 шага Seq Scan (Sequential Scanning), что означает последовательное сканирование всех строк таблицы. В скобках указаны различные оценки (estimates) выполнения запроса: - первое число в cost обозначает время, которое проходит, прежде чем начнётся этап вывода данных; - второе число в cost обозначает общую стоимость выполнения. Общая стоимость выполнения = время начала вывода данных + время окончания вывода данных; - число в rows указывает на число строк, которое должен обработать запрос; - число в width отображает количество байт, которое обработает запрос для вывода нужных строк. Давайте теперь рассмотрим другой пример:
EXPLAIN SELECT * FROM retail.product_dim WHERE category IN ('Furniture', 'Technology');Запрос вернёт нам такой результат:
Seq Scan on product_dim (cost=0.00..58.14 rows=862 width=91) -> Filter: ((category)::text = ANY ('{Furniture,Technology}'::text[]))Как мы видим, оператор WHERE добавил шаг Filter. Здесь важно сказать, что план выполнения запроса, как правило, читается снизу-вверх или справа-налево. В данном случае мы читаем наш план снизу вверх: 1) Первым выполняется Filter, который отбирает только те строки, где категория товара равна или Furniture, или Technology. 2) После фильтрации происходит последовательное сканирование таблицы (отфильтрованных строк). Теперь давайте сделаем трюк и создадим индекс на столбец category:
CREATE INDEX category_idx on retail.product_dim (category);И снова выполним запрос:
EXPLAIN SELECT * FROM retail.product_dim WHERE category IN ('Furniture', 'Technology');Теперь этот же запрос выдаёт нам такой результат:
Index Scan using category_idx on product_dim (cost=0.28..41.71 rows=862 width=91) Index Cond: ((category)::text = ANY ('{Furniture,Technology}'::text[]))Как мы видим, теперь вместо 2-х этапов в плане выполнения запроса только один - Index Scan (сканирование индекса). Index Cond объясняет, почему происходит сканирование индекса, указывая, что в WHERE мы фильтруемся по полю, на которое и создали индекс. Также можно заметить, что добавление индекса сократило общую стоимость выполнения запроса с 58.14 до 41.71. Здесь мы имеем наглядный пример того, как индексы могут оптимизировать скорость выполнения запроса. Но не забываем, что индексами нужно пользоваться с умом (об этом я писал здесь). На сегодня всё. Ждите 2 часть🙂
Индексы - на логическом* уровне это отсортированные ключи колонки таблицы (для которой и создаётся индекс), которые имеют указатели на местонахождение строк основной таблицы со значением колонки в индексе. Если сильно упростить, то индекс в базах данных очень похож на индекс в конце книг. Когда вы открываете индекс на последних страницах книги, у вас есть список ключевых слов, отсортированных от А до Я. Для каждого слова есть номера страниц, где это слово упоминается, что облегчает поиск. По такому же принципу работают индексы и в БД. Важно сказать о том, что индексы в большей степени используются в традиционных реляционных СУБД (таких как PostgreSQL, MySQL, Microsoft SQL Server и т.д.). Современные колоночные решения, такие как Google BigQuery, Snowflake или Amazon Redshift используют специальный слой метаданных, который решает задачу повышения эффективности поиска и скорости выполнения запросов. Когда использовать: - на больших таблицах; - когда увеличение скорости выполнения запросов за счёт индексов…
Онлайн-курс «Data Engineer» от сервиса Яндекс Практикум. 6.5 месяцев обучения на инженера данных с выдачей диплома о профессиональной переподготовке.
- Да, это база для практически любой IT-профессии
- Нет, можно работать и без этого
- Свой вариант в комментариях
- Хочу посмотреть результаты
SELECT * FROM orders WHERE segment = 'Corporate';
Мы можем создать индекс на столбец "segment", чтобы увеличить скорость выполнения запроса. Например, в PostgreSQL индекс можно создать так:
CREATE INDEX segment_idx on orders (segment);
Т.е. создавать индексы - быстро и просто.
Индексы могут быть также составными - включать несколько столбцов.
Когда не использовать:
- на небольших таблицах. Индексы требуют дополнительного пространства для их хранения. Поэтому, если скорость выполнения запросов без индекса вас вполне устраивает, то и не нужно использовать дополнительные ресурсы для хранения индексов;
- на колонках с большим количеством null-значений;
- на часто обновляющихся таблицах. Частые операции вставки и обновления полей таблиц повышают нагрузку на СУБД, так как значения нужно записать/обновить в двух местах - в основной таблице и в индексе. Если вы часто производите удаления в основной таблице, то индекс становится фрагментированным (т.е. включает в себя пустые "листы"), что приводит к его неэффективности;
- на колнках с низкой кардинальностью (низким количеством уникальных значений). Например, если ваша колонка, на которую вы создаёте индекс, включает в себя только True/False значения, создание индекса не принесёт вам много профита.
* Я не просто в определении индекса написал "на логическом уровне". Логический уровень - это абстракция, которая позволяет описать объект обобщённо и как можно проще без углубления в детали. Есть ещё физический уровень, который описывает, чем на самом деле "под капотом" являются индексы. На физическом уровне для создания индексов используются специальные структуры данных: как правило, это B+tree или hash-таблицы. О структурах данных я тоже напишу, но сейчас я хочу двигаться от логического уровня к физическому для упрощения восприятия.SELECT * FROM orders WHERE order_date = '2021-12-15';Так как наша таблица партиционирована по дате заказа, движок просканирует только одну партицию "2021-12-15", а не всю таблицу (в случае, если партиционирование не используется). Скорость выполнения такого запроса вырастет во много раз. Когда не использовать: не нужно использовать партиционирование на небольших таблицах. Если говорить о традиционных реляционных СУБД, создание и поддержка партиций является не самой тривиальной задачей, и, если таблица небольшая, выгода от партиций будет намного меньше затрат на их создание и поддержку. Более того, на небольших таблицах партиционирование может даже снижать производительность запросов.
Joriy rejangiz faqat 5 ta kanal uchun analitika imkoniyatini beradi. Ko'proq olish uchun, iltimos, boshqa reja tanlang.