Как найти неиспользуемые строки в таблице измерений

#sql-server #tsql #data-warehouse #sql-data-warehouse

#sql-сервер #tsql #хранилище данных #sql-хранилище данных

Вопрос:

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

Одна из вещей, которые я пытаюсь сделать, — это удалить записи измерений, которые больше не используются. Таблицы фактов регулярно поддерживаются, а старые снимки удаляются. Поскольку измерения не поддерживались таким образом, в таблице есть много строк, значение первичного ключа которых больше не отображается ни в одной из связанных таблиц фактов. Все таблицы фактов имеют ограничения внешнего ключа.

Есть ли способ найти строки таблицы, значение первичного ключа которых больше не отображается ни в одной из таблиц, связанных с ограничением внешнего ключа?

Я попытался написать скрипт для отслеживания этого. В основном это:

 select key from dimension 
where not exists (select 1 from fact1 where fk = pk) 
and not exists (select 1 from fact2 where fk = pk) 
and not exists (select 1 from fact3 where fk = pk)
  

Но при большом количестве связанных таблиц этот запрос умирает через некоторое время — по крайней мере, моя management Studio потерпела крах. Поэтому я не уверен, есть ли какие-либо другие варианты.

Комментарии:

1. Пожалуйста, предоставьте образцы данных и желаемые выходные данные в виде форматированного текста , а не изображений.

2. Это никогда не будет быстро. Наиболее удобный способ — генерировать запросы, которые перемещаются по всем таблицам фактов, чтобы выбрать DISTINCT значения для каждого столбца измерения во временной таблице, а затем удалить строки измерения, которые не встречаются в этой таблице. (Некластеризованный) индекс columnstore для этих столбцов значительно ускорил бы это (и, возможно, было бы неплохо иметь его вообще на складе).

3. Да, я немного боялся, что так и будет. На самом деле я уже создал код для генерации инструкций для этого. Но, по крайней мере, теперь я знаю, что не упустил лучшего способа сделать это.

Ответ №1:

мы должны были сделать что-то похожее на это у одного из моих клиентов. Запрос, подобный вашему с «не существует …. и не существует …. и не существует ….», выполнялся ~ 22 часа, прежде чем мы изменили нашу стратегию, чтобы справиться с этим за ~ 20 минут.

Как предлагает Nsousa, вам нужно разделить запрос, чтобы SQL Server не обрабатывал все данные за один раз, без необходимости используя tempdb и все другие вещи.

Сначала создайте новую таблицу со всеми ключами в ней. Причина создания этой таблицы заключается в том, чтобы не читать полное сканирование таблицы для каждого запроса, имея больше ключей на странице размером 8 кб, и иметь дело со все меньшим набором ключей после каждого удаления.

 create table DimensionkeysToDelete (Dimkey char(32) primary key nonclustered);
insert into DimensionkeysToDelete 
select key from dimension order by key; 
  

Затем, вместо удаления неиспользуемого ключа, удалите ключи, существующие в таблице фактов, начиная с таблицы фактов, в которой наименьшее количество строк.
Убедитесь, что таблица фактов имеет надлежащую индексацию для повышения производительности.

 delete from DimensionkeysToDelete 
from DimensionkeysToDelete d 
inner join fact1 on f.fk = d.Dimkey;

delete from DimensionkeysToDelete 
from DimensionkeysToDelete d 
inner join fact2 on f.fk = d.Dimkey;

delete from DimensionkeysToDelete 
from DimensionkeysToDelete d 
inner join fact3 on f.fk = d.Dimkey;
  

После завершения работы со всеми таблицами фактов в DimensionkeysToDelete остаются только неиспользуемые ключи. Чтобы ответить на ваш вопрос, просто выполните select в этой таблице, чтобы получить все неиспользуемые ключи для этого конкретного измерения, или соедините его с измерением, чтобы получить данные.

Но, насколько я понимаю, ваши потребности в очистке вашего хранилища используйте эту таблицу для удаления из исходной таблицы измерений. На этом шаге вы также можете предпринять некоторые действия в целях аудита (например: вставить в таблицу аудита ‘Key ‘ key ‘ deleted on преобразовать (datetime, getdate(),121) ‘ по сценарию X’ …. )

Я думаю, что это можно оптимизировать, взгляните на план выполнения, но мой клиент был доволен этим, поэтому нам не пришлось прилагать к этому особых усилий.

Комментарии:

1. Рискуя заявить очевидное — я предполагаю, что ни одно из измерений, из которых вы хотите удалить записи, не является SCD2 (или аналогичным)? Если они есть, у вас, очевидно, есть более сложная проблема, поскольку вам нужно будет исправить даты начала / окончания оставшихся записей, чтобы устранить любые пробелы

Ответ №2:

Возможно, вы захотите разделить это на разные запросы. Проверьте неиспользуемые строки в fact1, затем в fact2 и т.д. по отдельности. Затем пересеките все эти результаты, чтобы получить неиспользуемые строки во всех таблицах фактов.

Я бы также предложил использовать левое внешнее соединение вместо вложенных запросов, подсчитывая строки в таблице фактов для каждого pk и отфильтровывая из результирующего набора те, которые имеют ненулевое количество.

Ваш запрос будет испытывать трудности, поскольку он будет сканировать каждую таблицу фактов одновременно.