2013-04-25 2 views
2

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

Этот запрос выполняется медленно, и меня попросили ускорить его. Первое, что выпрыгивает на меня, заключается в том, что не существует насущной потребности в вложенном заявлении SELECT внутри внешнего предложения FROM. В том, что вложенные SELECT, также, кажется, несколько полей, которые не являются необходимыми (vegetable, broomhilda, devoured и т. Д.). Я также скептически отношусь к использованию объединений («*=» вместо «INNER JOIN ... ON»).

SELECT 
    dog_id, 
    cat_metadata, 
    rhino_id, 
    buffalo_id, 
    animal_metadata, 
    has_4_Legs, 
    is_mammal, 
    is_carnivore, 
    num_teeth, 
    does_hibernate, 
    last_spotted_by, 
    last_spotted_date, 
    purchased_by, 
    purchased_date, 
    allegator_id, 
    cow_id, 
    cow_name, 
    cow_alias, 
    can_be_ridden 
FROM 
(
    SELECT 
     mp.dog_id as dog_id, 
     ts.cat_metadata + '-yoyo' as cat_metadata, 
     mp.rhino_id as rhino_id, 
     mp.buffalo_id as buffalo_id, 
     mp.animal_metadata as animal_metadata, 
     isnull(mp.has_4_Legs, 0) as has_4_Legs, 
     isnull(mp.is_mammal, 0) as is_mammal, 
     isnull(mp.is_carnivore, 0) as is_carnivore, 
     isnull(mp.num_teeth, 0) as num_teeth, 
     isnull(mp.does_hibernate, 0) as does_hibernate, 
     jungle_info.explorer as last_spotted_by, 
     exploring_journal.spotted_datetime as last_spotted_date, 
     jungle_info.explorer as purchased_by, 
     early_exploreration_journal.spotted_datetime as purchased_date, 
     alleg_id as allegator_id, 
     ho.cow_id, 
     ho.cow_name, 
     ho.cow_alias, 
     isnull(mp.is_ridable,0) as can_be_ridden, 
     ts.cat_metadata as broomhilda, 
     ts.squirrel as vegetable, 
     convert (varchar(15), mp.rhino_id) as tms_id, 
     0 as devoured 
    FROM 
     mammal_pickles mp, 
     very_tricky_animals vt, 
     possibly_venomous pv, 
     possibly_carniv_and_tall pct, 
     tall_and_skinny ts, 
     tall_and_skinny_type ptt, 
     exploration_history last_exploration_history, 
     master_exploration_journal exploring_journal, 
     adventurer jungle_info, 
     exploration_history first_exploration_history, 
     master_exploration_journal early_exploreration_journal, 
     adventurer jungle_info, 
     hunting_orders ho 
    WHERE 
     mp.exploring_strategy_id = 47 
     and mp.cow_id = ho.cow_id 
     and ho.cow_id IN (20, 30, 50) 
     and mp.rhino_id = vt.rhino_id 
     and vt.version_id = pv.version_id 
     and pv.possibly_carniv_and_tall_id = pct.possibly_carniv_and_tall_id 
     and vt.tall_and_skinny_id = ts.tall_and_skinny_id 
     and ts.tall_and_skinny_type_id = ptt.tall_and_skinny_type_id 
     and mp.alleg_id *= last_exploration_history.exploration_history_id 
     and last_exploration_history.master_exploration_journal_id *= exploring_journal.master_exploration_journal_id 
     and exploring_journal.person_id *= jungle_info.person_id 
     and mp.first_exploration_history_id *= first_exploration_history.exploration_history_id 
     and first_exploration_history.master_exploration_journal_id *= early_exploreration_journal.master_exploration_journal_id 
     and early_exploreration_journal.person_id *= jungle_info.person_id 
) TEMP_TBL 

Так я спрашиваю:

  • Я правильно о вложенной SELECT?
  • Правильно ли я делаю ненужные поля внутри вложенных SELECT?
  • Я правильно отношусь к структуре/синтаксису/использованию соединений?
  • Есть ли что-нибудь еще о структуре/характере этого запроса, который выскакивает на вас как ужасно неэффективный/медленный?

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

+2

Вложенный SELECT может или не может обеспечить удар производительности. Это зависит от плана выполнения (я не могу сказать вам, так как много моделей для моделирования). Если он использует временную таблицу, то обязательно удалите вложенный SELECT (вы можете узнать, используя план EXPLAIN). В противном случае дополнительные поля ничего не повредят, если они не потребуют ненужного соединения. Опять же, это зависит от того, использует ли план выполнения временную таблицу (оптимизатор удалит ненужные таблицы из запроса, если первый запрос не скопирован во временную таблицу). – jtv4k

+0

Спасибо @ jtv4k (+1) - чтобы уточнить, вы говорите, что * если * план выполнения (который я вижу через 'EXPLAIN') показывает Sybase как использование' TEMP_TBL', тогда мне определенно нужно удалить вложенные 'SELECT'? Если это то, что вы говорите, можете ли вы объяснить, почему вложенные «SELECT» и связанные с ним «TEMP_TBL» являются «плохими» (медленными) для плана выполнения? – 2013-04-25 17:51:32

+0

Ahhh, я начинаю «достать». Если я правильно понимаю: если подзапрос скопирован в временную таблицу, то оптимизатор не удалит unnessary join; в противном случае ненужные соединения будут оставаться частью плана выполнения, и они будут отрицательно влиять на производительность? ** Это справедливая оценка? ** Еще раз спасибо! – 2013-04-25 17:56:42

ответ

0
  • Правильно ли я вложен в SELECT?

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

  • Я правильно отношусь к ненужным полям внутри вложенного SELECT?

Да, особенно учитывая, что некоторые из них вообще не отображаются в конечном списке полей.

  • Я правильно отношусь к структуре/синтаксису/использованию соединений?

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

  • Есть ли что-нибудь еще в отношении структуры/характера этого запроса, который выдается на вас как ужасно неэффективный/медленный?

Да.

Во-первых, у вас есть некоторые вычисления, которые не нужны, например. convert (varchar(15), mp.rhino_id) as tms_id. Возможно, соединение или два, но я, по общему признанию, не посмотрел на детали запроса.

Далее у вас может возникнуть проблема с самой конструкцией db, например. поле cow_id. (Серьезно? :-))

Последнее, что-то иногда можно сказать о выполнении нескольких запросов вместо одного, чтобы избежать тонны объединений.

В блоге, например, обычно рекомендуется захватить верхние 10 сообщений, а затем использовать отдельный запрос для извлечения их тегов (где id (id1, id2 и т. Д.)). В вашем случае, селективная часть, кажется, здесь:

mp.exploring_strategy_id = 47 
    and mp.cow_id = ho.cow_id 
    and ho.cow_id IN (20, 30, 50) 

так возможно выделить эту часть в одном запросе, а затем построить in() положения, используя полученные идентификаторы, и принести косметические биты и куски в одном или более отдельные запросы.

О, и, как указано Гордоном, проверьте свои индексы. Но тогда обратите внимание, что индексы могут оказаться мало полезными, не разбивая запрос на более управляемые части.

0

Я бы предложил следующий подход.

Сначала перепишите запрос, используя стандартные соединения ANSI с предложением on. Это облегчит понимание условий и фильтрации. Кроме того, это «безопасно» - вы должны получать точно такие же результаты, что и текущая версия. Будьте осторожны, потому что *= является внешним соединением, поэтому не все является внутренним соединением.

Я сомневаюсь, что этот шаг улучшит производительность.

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

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

Затем рассмотрите индексацию полей, используемых для фильтрации (в предложении where).

И узнайте, как использовать возможности объяснения. Любой вложенный цикл объединяется (без индекса) как вероятный виновник проблем с производительностью.

Что касается вложенного выбора, я думаю, что Sybase достаточно умен, чтобы «делать правильные вещи». Даже если он выписал и перечитал результирующий набор, это, вероятно, оказало бы незначительное влияние на запрос по сравнению с получением прав на объединение.

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

+0

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

0

Я отвечу на некоторые из ваших вопросов.

Вы считаете, что поля (растительные, broomhilda, пожираемые) во вложенном SELECT могут вызывать проблемы с производительностью. Не обязательно. Два неиспользуемых поля (растительный, broomhilda) во вложенном SELECT находятся из таблицы ts, но поле cat_metadata, которое используется, также находится в таблице ts. Поэтому, если cat_metadata покрывается индексом, используемым в таблице ts, не будет никакого влияния на производительность.Потому что, чтобы извлечь поле cat_metadata, страница данных из таблицы должна быть выбрана в любом случае. Извлечение других двух полей займет немного процессора, вот и все. Так что не беспокойтесь об этом. Поглощенное поле также является константой. Это также не повлияет на производительность.

Деннис указал на использование преобразования функции преобразования (varchar (15), mp.rhino_id). Я не согласен с тем, что это повлияет на производительность, поскольку оно будет потреблять только процессор.

Наконец, я бы сказал, попробуйте использовать подсчитанную таблицу count до 13, так как там есть 13 таблиц. Sybase использует четыре таблицы одновременно для оптимизации.

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