1

У меня есть хранилище данных SQL Server с дизайном Fact Constellation Schema. Я должен построить отчет по 4 объектам/просмотров:Нежелательная оптимизация запросов в вложенном виде

  1. продаж Actuals - таблица фактов [Продажи]
  2. продаж Targets - таблица фактов [Цели]
  3. Stocks - таблица фактов [инвентаризации]
  4. Входящее - таблица фактов [Транзитный]

Все объекты/виды имеют ту же сигнатуру, например:

Sales actuals: ProductID, RegionID, SalesManagerID, ..., <product data>, <region data>, ..., Quantity; 
Sales targets: ProductID, --null--, SalesManagerID, ..., <product data>, -----null----, ..., Quantity; 
Stocks:  ProductID, RegionID, -----null-----, ..., <product data>, <region data>, ..., Quantity; 
... 

Для достижения такой подписи каждый объект/представление получают из таблицы фактов и 5-6 таблиц измерений. Таблицы измерений распределяются между объектами (таблица с данными о продукте, таблица с данными региона, ...).

Для расчета каждого вида просмотра требуется не более 5-10 секунд SQL.

СЕЙЧАС, что я хочу, чтобы объединить их в единый отчет, я делаю это:

Select * from [Sales actuals] 
UNION 
Select * from [Sales targets] 
UNION 
Select * from [Stocks] 
UNION 
Select * from [Inbound] 

А вот SQL даже не удается получить 10% данных в течение 1 минуты. Похоже, что оптимизатор запросов объединяет 4 таблицы фактов в один большой вектор и прикрепляет таблицу измерений, что приводит к безумию системы.

Я хочу, чтобы объекты/объекты были инкапсулированы. Это означает, что двигатель должен сначала вычислить представления (4 * 5 с = 20 секунд). и только затем примените операцию Union (10 секунд + некоторые накладные расходы) для получения результата.

Вопрос: как я могу отключить оптимизацию запросов в вложенных представлениях для достижения такой «вычислительной инкапсуляции»?

Выполнение, как и в компиляторе: сначала объединение таблиц фактов, а затем объединение таблиц измерений - это не вариант, потому что я хочу, чтобы код был интерпретируемым и многоразовым.

Заранее благодарен! Constantine

+0

Я бы подумал, что если вы выберете 4 временных таблицы и затем соедините их, вы можете получить то, чего хотите достичь. –

+2

Попробуйте изменить 'UNION' на' UNION ALL'. Союз может занять много времени, потому что он удаляет дубликаты. – valex

ответ

0

Для начала вы, вероятно, захотите изменить UNION на UNION ALL?!?

Чтобы сервер делал то, что вы хотите, вы могли бы добавить подсказку стола NOEXPAND в «последнем» представлении; но, честно говоря, я никогда не видел, чтобы это было полезно для общей производительности.

мне интересно, как умный оптимизатор запросов будет, если вы пытались что-то вдоль линий:

;WITH facts (dimension_ids & measures) 
     AS (Select * from [Sales actuals] 
      UNION ALL 
      Select * from [Sales targets] 
      UNION ALL 
      Select * from [Stocks] 
      UNION ALL 
      Select * from [Inbound]) 
SELECT dimension_values, measures 
    FROM facts 
    JOIN dimension1 ON dim1.id = facts.dim1_id 
       AND dim1.property = @filter_dim1 
    JOIN dimension2 ON dim2.id = ... 

etc... 

Это, вероятно, будет делать то, что вы хотите, хотя я не уверен, что это будет лучше, чем

SELECT dimension_values, measures 
    FROM [Sales actuals] fct 
    JOIN dimension1 ON dim1.id = fct.dim1_id 
       AND dim1.property = @filter_dim1 
    JOIN dimension2 ON dim2.id = ... 

UNION ALL 

SELECT dimension_values, measures 
    FROM [Sales targets] fct 
    JOIN dimension1 ON dim1.id = fct.dim1_id 
       AND dim1.property = @filter_dim1 
    JOIN dimension2 ON dim2.id = ... 

UNION ALL 
etc... 

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

PS: Я знаю, что это будет звучать «базовым», но вы сначала запустили sp_updatestats?

 Смежные вопросы

  • Нет связанных вопросов^_^