Главная страница  Карта сайта  Печать  Написать письмо  RSS
Войти
Персональный сайт
Стеллецкого Владимира
Обновлено: 20.05.2021 г.

Примеры с SQL

«   ‹   1   2   3   4   5   следующая ›   последняя »

Heap-таблицы и forwarded-записи в SQL Server (20.05.2021) #

Интересная статья про кучи. Основные тезисы:

  • Куча — это таблица без кластерного индекса. Данные в куче хранятся без какого-либо логического порядка. Между страницами нет никакой связи.
  • Таблицы-кучи в базе данных можно найти с помощью системного представления sys.indexes (см. мою заметку)
  • Для просмотра дополнительной информации (процент фрагментации индекса, тип индекса, количество страниц и количество forwarded-записей) можно использовать динамическую административную функцию (Dynamic Management Function, DMF) sys.dm_db_index_physical_stats (в DETAILED-режиме)
  • При изменении данных, если SQL Server не может разместить новые данные на существующей странице из-за их большого размера, данные размещаются в другом месте, а на данной странице SQL Server вставляет Forwarded Record (запись о перенаправлении). Также в новом местоположении данных добавляется указатель в обратную сторону на созданную Forwarded Record для отслеживания цепочки forwarding-указателей в случае перемещения данных.
  • Большое количество перемещений влияет на количество логических чтений при выборке данных (их можно посмотреть, если перед выполнением запроса включить сбор и отображение необходимой статистики - SET STATISTICS IO ON).

Варианты решения проблемы большого количество логических чтений из-за forwarded-записей (если она есть):

  • Использование типов данных фиксированной длины (при изменении данные поместятся на уже выделенное место и перенаправления не будет)
  • Отказываться от кучи (добавлением кластерного индекса)
  • Мониторинг и регулярное перестроение кучи (ALTER TABLE ... REBUILD)

Тёмная сторона SQL Server In-Memory OLTP (12.05.2021) #

Выдержка из статьи: принимая решение об использовании In-Memory OLTP в промышленном окружении нужно обязательно учитывать, что:

  1. Файловую группу In-Memory нельзя удалить из БД, она останется с вами навсегда.
  2. Файловая группа In-Memory, при совпадении ряда условий, может быстро и значительно расти.
  3. Таблицы, объявленные как SCHEMA_ONLY, не генерируют IO и не используют Data и Delta файлы на диске, но эти файлы для них создаются при каждом CHECKPOINT'е.
  4. При использовании Availability Group, файловая группа In-Memory будет гораздо больше, чем в точно такой же БД, не входящей в Availability Group.

Сводные таблицы в SQL (03.07.2020) #

Интересная статья с описанием нескольких способов формирования Сводных таблиц в SQL (есть примеры для MySQL, MSSQL Server, Oracle и PostgreSQL). Пополнил знания по нескольким операторам SQL:

  • Выражение COALESCE - замена часто используюмому мною IsNull. У IsNull, как оказалось, есть одна неприятная особенность - тип результата определяется типом первого параметра, что может привести к усечению данных.
    -- Пример "некорректной" работы IsNull
    DECLARE @st VARCHAR(10), @st1 VARCHAR(20)
    SET @st1 = 'Привет, Владимир!'
    SELECT ISNULL(@st, @st1)
    
  • Аргумент ROLLUP у GROUP BY - для создания строки Итого при группировке.

Также взял на вооружение несколько подсмотренных в статье интересных приёмов.

Временные таблицы и табличные переменные (28.12.2018) #

Наткнулся на старенькую статью посвященную сравнению временных таблиц (create table #T (…)) и табличных переменных (declare @T table (…)).

Приведу ключевые различия (в статье приводится подробное сравнение и примеры):

  1. Табличные переменные не учитывают транзакции (откат транзакции не вернёт исходного значения).
  2. Процедуры с временными таблицами не могут быть предварительно скомпилированы (компиляция будет осуществляться при каждом вызове, что может сказаться на времени, особенно для больших процедур).
  3. Табличные переменные существуют только в пределах видимости переменных.

Касательно быстродействия в каждом конкретном случае правильнее проводить эксперименты.

Классные индексы (25.09.2018) #

Время от времени натыкаюсь в нашей базе данных на MS SQL сервере на разные интересные моменты. Представим себе таблицу на почти 5 млн. строк, например, с заказами. Вся таблица нас не интересует, возьмём только поле Статус заказа.

Внимание вопрос: насколько и в каких случаях будет эффективным индекс по полю со следующим распределением значений:

Распределение данных в таблице

-- пример запроса для получения такого распределения
select
       r.[Status],
       count(*) as cnt
from dbo.[TableOrder] r
group by r.[Status]  

Думаю, что не особо и только в очень частном случае.

Или представим себе таблицу на пару десятков млн. строк с индексом по трём битовым полям (да-да именно битовым, то есть максимум три значения у каждого).

Тут, как говорится, вообще без комментариев.

Запросы в текущее время потребляющие память (14.01.2018) #

Предлагаю запрос, который отображает запросы с MS SQL-сервера, которые потребляют память в текущий момент (при выводе информации применяется фильтр, отсекающий запросы, потребляющие менее 500 МБ). Иногда с его помощью удаётся найти неэффективные запросы, которые следует рассмотреть повнимательнее и, возможно, оптимизировать или переписать.

Кратко приведу информацию о колонках:

  • Данные о пользователе (имя и хост)
  • Время запроса (request_time) и выделения (grant_time) памяти
  • Объем запрошенной (requested_memory_kb) и выделенной (granted_memory_kb) памяти в килобайтах
  • Информация по использованию памяти: сколько потребовалось (required_memory_kb), было использовано (used_memory_kb) и максимальное значение (max_used_memory_kb)
  • Коэффициент "стоимости" запроса (query_cost)
  • Время ожидания (wait_time_ms)
  • Сам выполняющийся запрос (query_text)
  • Информация о выполняемом запросе (event_info)
  • Ссылка на план выполнения запроса (query_plan)
-- запросы в текущее время потребляющие память
SELECT mg.session_id,
       CAST(es.nt_user_name as varchar) as nt_user_name,
       CAST(es.host_name as varchar) as host_name,
       mg.request_time,
       mg.grant_time,
       mg.requested_memory_kb,
       mg.granted_memory_kb,
       mg.required_memory_kb,
       mg.used_memory_kb,
       mg.max_used_memory_kb,
       mg.query_cost,
       mg.resource_semaphore_id,
       mg.wait_time_ms,
       st.[text] as query_text,
       ib.event_info,
       qp.query_plan
FROM sys.dm_exec_query_memory_grants AS mg
     INNER JOIN sys.dm_exec_sessions AS es
                ON es.session_id = mg.session_id
     CROSS APPLY sys.dm_exec_input_buffer(mg.session_id, NULL) AS ib
     CROSS APPLY sys.dm_exec_sql_text(mg.sql_handle) AS st
     CROSS APPLY sys.dm_exec_query_plan(mg.plan_handle) AS qp
WHERE mg.requested_memory_kb > 500000
ORDER BY mg.requested_memory_kb DESC

С помощью этого запроса обнаружили у себя запросы с аномальным потреблением памяти (10Гб, 20Гб и даже 40Гб).

Как заменить старые индексы и не сломать систему? (15.12.2017) #

Возможно, многие сталкивались с исторически сложившейся за годы, до появления на проекте, ситуацией, когда на таблице создали все возможные индексы со всеми include’ами. Я видела индекс на доставшейся «в наследство» БД, который содержал все поля таблицы. При этом, не всегда есть возможность быстро поменять индексы, так как часто нужна гарантия, что изменения не повлияют на работоспособность системы.

https://habrahabr.ru/post/344284/

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

«   ‹   1   2   3   4   5   следующая ›   последняя »

  Вы 51 954 посетитель этой странички
с 07 октября 2006 года
© http://svv-home.ru
О сайте