Проблема с производительностью Teradata и пример

Я столкнулся с проблемой в нашей среде контроля качества Teradata, из-за которой простой запрос, который выполнялся менее чем за 1 минуту, теперь занимает 12 минут. Этот выбор извлекает 5 полей на основе простого внутреннего соединения

select a.material
    , b.season
    , b.theme
    , b.collection
from SalesOrders_view.Allocation_Deliveries_cur a
inner join SalesOrders_view.Material_Attributes_cur b
    on a.material = b.material;

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

Общий объем составляет менее 1,1 млн записей в SalesOrders.Allocation_Deliveries и 129 тыс записей в SalesOrders.Material_Attributes. Это небольшие наборы данных.

Я сравнил планы объяснения для обеих сред и обнаружил резкую разницу в предполагаемом объеме спула на первом этапе соединения. Оценка в Production находится на деньгах, в то время как оценка в QA на порядок меньше. Однако данные и таблицы / представления идентичны в обеих системах, и мы собрали статистику всеми возможными способами, и мы можем видеть конкретные демографические данные таблиц в обеих системах как идентичные.

Наконец, этот запрос всегда возвращается менее чем за минуту во всех средах, включая QA, как это все еще происходит в производственной среде. Это скрытое поведение наблюдается недавно, примерно на прошлой неделе. Я обсуждал это с нашим администратором баз данных, и у нас не было никаких изменений в программном обеспечении или конфигурации. Он новичок, но, кажется, знает, что делает, но все еще увлекается новой средой.

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

Любая помощь приветствуется. Заранее спасибо. Пэт

Это план Explain от QA. Обратите внимание на очень низкую оценку в шаге 5 (144 строки). В Prod то же Explain показывает> 1 M строк, что близко к тому, что я знаю.

Explain select a.material
    , b.season
    , b.theme
    , b.collection
from SalesOrders_view.Allocation_Deliveries a
inner join SalesOrders_view.Material_Attributes_cur b
    on a.material = b.material;

  1) First, we lock SalesOrders.Allocation_Deliveries in view
     SalesOrders_view.Allocation_Deliveries for access, and we lock
     SalesOrders.Material_Attributes in view SalesOrders_view.Material_Attributes_cur for
     access. 
  2) Next, we do an all-AMPs SUM step to aggregate from
     SalesOrders.Material_Attributes in view SalesOrders_view.Material_Attributes_cur by way
     of an all-rows scan with no residual conditions
     , grouping by field1 ( SalesOrders.Material_Attributes.material
     ,SalesOrders.Material_Attributes.season ,SalesOrders.Material_Attributes.theme
     ,SalesOrders.Material_Attributes.theme ,SalesOrders.Material_Attributes.af_grdval
     ,SalesOrders.Material_Attributes.af_stcat
     ,SalesOrders.Material_Attributes.Material_Attributes_SRC_SYS_NM).  Aggregate
     Intermediate Results are computed locally, then placed in Spool 4. 
     The size of Spool 4 is estimated with high confidence to be
     129,144 rows (41,713,512 bytes).  The estimated time for this step
     is 0.06 seconds. 
  3) We execute the following steps in parallel. 
       1) We do an all-AMPs RETRIEVE step from Spool 4 (Last Use) by
          way of an all-rows scan into Spool 2 (all_amps), which is
          redistributed by the hash code of (
          SalesOrders.Material_Attributes.Field_9,
          SalesOrders.Material_Attributes.Material_Attributes_SRC_SYS_NM,
          SalesOrders.Material_Attributes.Field_7, SalesOrders.Material_Attributes.Field_6,
          SalesOrders.Material_Attributes.theme, SalesOrders.Material_Attributes.theme,
          SalesOrders.Material_Attributes.season, SalesOrders.Material_Attributes.material)
          to all AMPs.  Then we do a SORT to order Spool 2 by row hash
          and the sort key in spool field1 eliminating duplicate rows. 
          The size of Spool 2 is estimated with low confidence to be
          129,144 rows (23,504,208 bytes).  The estimated time for this
          step is 0.11 seconds. 
       2) We do an all-AMPs RETRIEVE step from SalesOrders.Material_Attributes in
          view SalesOrders_view.Material_Attributes_cur by way of an all-rows scan
          with no residual conditions locking for access into Spool 6
          (all_amps), which is redistributed by the hash code of (
          SalesOrders.Material_Attributes.material, SalesOrders.Material_Attributes.season,
          SalesOrders.Material_Attributes.theme, SalesOrders.Material_Attributes.theme,
          SalesOrders.Material_Attributes.Material_Attributes_SRC_SYS_NM,
          SalesOrders.Material_Attributes.Material_Attributes_UPD_TS, (CASE WHEN (NOT
          (SalesOrders.Material_Attributes.af_stcat IS NULL )) THEN
          (SalesOrders.Material_Attributes.af_stcat) ELSE ('') END )(VARCHAR(16),
          CHARACTER SET UNICODE, NOT CASESPECIFIC), (CASE WHEN (NOT
          (SalesOrders.Material_Attributes.af_grdval IS NULL )) THEN
          (SalesOrders.Material_Attributes.af_grdval) ELSE ('') END )(VARCHAR(8),
          CHARACTER SET UNICODE, NOT CASESPECIFIC)) to all AMPs.  Then
          we do a SORT to order Spool 6 by row hash.  The size of Spool
          6 is estimated with high confidence to be 129,144 rows (
          13,430,976 bytes).  The estimated time for this step is 0.08
          seconds. 
  4) We do an all-AMPs RETRIEVE step from Spool 2 (Last Use) by way of
     an all-rows scan into Spool 7 (all_amps), which is built locally
     on the AMPs.  Then we do a SORT to order Spool 7 by the hash code
     of (SalesOrders.Material_Attributes.material, SalesOrders.Material_Attributes.season,
     SalesOrders.Material_Attributes.theme, SalesOrders.Material_Attributes.theme,
     SalesOrders.Material_Attributes.Field_6, SalesOrders.Material_Attributes.Field_7,
     SalesOrders.Material_Attributes.Material_Attributes_SRC_SYS_NM,
     SalesOrders.Material_Attributes.Field_9).  The size of Spool 7 is estimated
     with low confidence to be 129,144 rows (13,301,832 bytes).  The
     estimated time for this step is 0.05 seconds. 
  5) We do an all-AMPs JOIN step from Spool 6 (Last Use) by way of an
     all-rows scan, which is joined to Spool 7 (Last Use) by way of an
     all-rows scan.  Spool 6 and Spool 7 are joined using an inclusion
     merge join, with a join condition of ("(material = material) AND
     ((season = season) AND ((theme = theme) AND ((theme =
     theme) AND (((( CASE WHEN (NOT (af_grdval IS NULL )) THEN
     (af_grdval) ELSE ('') END ))= Field_6) AND (((( CASE WHEN (NOT
     (AF_STCAT IS NULL )) THEN (AF_STCAT) ELSE ('') END ))= Field_7)
     AND ((Material_Attributes_SRC_SYS_NM = Material_Attributes_SRC_SYS_NM) AND
     (Material_Attributes_UPD_TS = Field_9 )))))))").  The result goes into Spool
     8 (all_amps), which is duplicated on all AMPs.  The size of Spool
     8 is estimated with low confidence to be 144 rows (5,616 bytes). 
     The estimated time for this step is 0.04 seconds. 
  6) We do an all-AMPs JOIN step from Spool 8 (Last Use) by way of an
     all-rows scan, which is joined to SalesOrders.Allocation_Deliveries in view
     SalesOrders_view.Allocation_Deliveries by way of an all-rows scan with no
     residual conditions.  Spool 8 and SalesOrders.Allocation_Deliveries are
     joined using a single partition hash_ join, with a join condition
     of ("SalesOrders.Allocation_Deliveries.material = material").  The result goes
     into Spool 1 (group_amps), which is built locally on the AMPs. 
     The size of Spool 1 is estimated with low confidence to be 3,858
     rows (146,604 bytes).  The estimated time for this step is 0.44
     seconds. 
  7) Finally, we send out an END TRANSACTION step to all AMPs involved
     in processing the request.
  -> The contents of Spool 1 are sent back to the user as the result of
     statement 1.  The total estimated time is 0.70 seconds.

Вот как выглядит распределение записей и SQL, который я использовал для генерации набора результатов

SELECT HASHAMP(HASHBUCKET(HASHROW( MATERIAL ))) AS
"AMP#",COUNT(*)
FROM EDW_LND_SAP_VIEW.EMDMMU01_CUR
GROUP BY 1
ORDER BY 2 DESC;

Максимальный результат: AMP 137 с 1093 строками Самый низкий: AMP 72 с 768 строками Общее количество AMP: 144


person apesa    schedule 08.01.2013    source источник
comment
Если план EXPLAIN отличается, то что-то между QA и производственной средой отличается. Можете поделиться планами EXPLAIN, определениями просмотра и определениями таблиц (мне все равно, если вы переименуете столбцы)? Как выглядит распределение данных для столбцов, участвующих в INNER JOIN? Имейте в виду, что для присоединения эти столбцы должны быть на одном AMP. Если есть перераспределение и перекос в данных, вы нашли свою проблему.   -  person Rob Paller    schedule 08.01.2013
comment
Роб, я добавил план объяснения от QA. Пришлось изменить имена, но они совпадают   -  person apesa    schedule 08.01.2013
comment
Кроме того, я использовал WinMerge, чтобы различать 2 плана объяснения, и единственные различия заключаются в количестве строк и оценках размера. Все они точны при сравнении их с фактическими реквизитами таблиц или с тем, что ожидается в соединении. Единственный выход из значения - это шаг 5 (только в QA), где отображается 144 строки. Это должно быть не более 1 M строк, как в Prod.   -  person apesa    schedule 09.01.2013
comment
У ваших систем PROD и QA одна и та же версия и одинаковый размер? Что вам говорят эти три запроса: select * from dbc.dbcinfo; выберите count (отдельный nodeid) как Number_of_nodes из dbc.resusagescpu; выберите hashamp () + 1 как Number_of_amps; Подумать только, Роб - хороший источник!   -  person BellevueBob    schedule 09.01.2013
comment
Спасибо за ответ, Боб, они дают одинаковые результаты в обеих системах. Выпуск 13.10.05.03, Версия 13.10.05.04, Поддержка стандартных языков, 4 узла и 144 А.   -  person apesa    schedule 09.01.2013
comment
ROb, я добавил результат просмотра распределения записей для ошибочной таблицы.   -  person apesa    schedule 09.01.2013


Ответы (1)


Рекомендации по статистике

Выполните следующее в PROD и QA и опубликуйте различия (при необходимости закройте имена столбцов):

DIAGNOSTIC HELPSTATS ON FOR SESSION;

EXPLAIN
select a.material
    , b.season
    , b.theme
    , b.collection
from SalesOrders_view.Allocation_Deliveries_cur a
inner join SalesOrders_view.Material_Attributes_cur b
    on a.material = b.material;

Эта диагностика при запуске вместе с командой EXPLAIN создает список рекомендуемых статистических данных, которые могут быть полезны оптимизатору при создании плана запроса с наименьшей стоимостью. Это может не дать никакой разницы или может указывать на что-то, что отличается между средами (данными или иным образом).

Просмотры и условия ПРИСОЕДИНЕНИЯ

На основании вашего плана EXPLAIN одно или оба представления в базе данных SalesOrders_View, похоже, используют предложение EXISTS. Это предложение EXISTS полагается на условие COALESCE (или явную логику CASE) для сравнения между столбцом в одной таблице, которая определена как NOT NULL, и столбцом в другой таблице, которая определена, чтобы допускать значения NULL. Это может повлиять на производительность этого соединения.

Распространение данных

Результаты вашего распространения получены из среды ПРОИЗВОДСТВА. (На основе количества AMPS и количества строк, показанных на AMP с самой высокой и самой низкой строками.) Как это выглядит для QA?

Изменить - 09.01.2013, 09:21

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

Собираете ли вы статистику PARTITION для своих таблиц, даже если они не являются таблицами PPI? Это помогает оптимизатору при оценке количества элементов.

Являетесь ли вы единственной рабочей нагрузкой в ​​системе контроля качества?

Вы смотрели метрики DBQL, чтобы сравнить потребление ЦП и операций ввода-вывода для запроса в каждой среде? Также обратите внимание на показатели IO Skew, CPU Skew и ненужные IO.

Есть ли у вас ограничители задержки в среде контроля качества, которые могут задерживать вашу рабочую нагрузку? Это даст вам представление о том, что требуется больше времени для запуска в среде QA, хотя на самом деле фактическое потребление ЦП и потребление ввода-вывода одинаковы для QA и PROD.

У вас есть доступ к Viewpoint?

Если да, то просматривали ли вы свой запрос, используя портлеты Мои запросы и / или Query Spotlight, чтобы наблюдать за его поведением?

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

Идентичны ли настройки DBS Control между средами? Попросите администратора базы данных взглянуть на это. Там есть настройки, которые могут повлиять на планы присоединения, используемые оптимизатором.

В конце концов, если данные, структуры таблиц, индексы и статистика совпадают в двух системах, чье оборудование и уровни исправлений TDBMS идентичны, вы не должны получать два разных плана EXPLAIN. Если это окажется так, я бы посоветовал вам связаться с GSC и вовлечь их.

person Rob Paller    schedule 08.01.2013
comment
Спасибо, Роб, результаты распределения фактически получены от QA и при суммировании равны общему количеству строк в этой таблице в QA. Количество AMPS и узлов одинаково как в QA, так и в Prod. Я выложу определение View. Следите за обновлениями для View Def и Result Set из вашего SQL. - person apesa; 09.01.2013
comment
Я запустил Explain со статистикой Diag Helpstats впереди, и получилось так же, как и раньше, поэтому я не публиковал повторно. Прогнал в обеих системах. Ни у одного из них не было рекомендованной статистики. - person apesa; 09.01.2013
comment
Наконец, я просмотрел взгляды. Первое представление - это просто представление базовой таблицы, ничего больше. Во втором представлении используется MAX () в метке времени загрузки для создания набора данных Delta. Я использую Coalesce для двух полей, которые могут иметь NULL, но эти поля не используются во внутреннем соединении. Внутреннее соединение просто использует Материал и никогда не имеет значения NULL. Я проверил, что в данных нет NULLS. - person apesa; 09.01.2013
comment
Следует отметить, что между Prod и QA нет заметных различий в конфигурации и / или данных. В обеих средах один и тот же SQL выполнялся менее чем за минуту. Теперь в QA для запуска требуется всего 12 минут. это действительно показывает разницу в планах Объяснения, но без реальной причины. Еще один к сведению, данные QA были скопированы из Prod около 2 месяцев назад, поэтому в этом случае с Master Data это действительно те же данные. Наконец, будучи данными SAP, я знаю их от и до и понимаю, чего ожидать в результате соединения. Это также Prod SQL, который тестируется и проверяется для получения правильных результатов. - person apesa; 09.01.2013
comment
Вот обновление. Похоже, это связано с данными, но мы не можем указать на настоящую проблему. Запрос «Медленно выполняющийся» исчез, как только мы удалили и повторно скопировали данные обратно в таблицу. Я просмотрел исходный набор данных в поисках плохих символов и т. Д., И ничего не вышло. Также данные, которые были скопированы обратно в таблицу, являются той же записью данных для записи. IDK, одна из таких проблем - person apesa; 16.01.2013