2012-05-29 5 views
1

Я не эксперт по SQL, пожалуйста, помогите, как я могу оптимизировать этот запрос?Оптимизация конкретного запроса sql

У меня нет индексов, только таблица, называемая master_table и другие таблицы, я должен оптимизировать этот запрос, чтобы получить те же результаты, я могу создавать индексы, если мне нужно, но я не могу изменить таблицу создания ... .

select month(date_hour), passenger, nationality, passport, airline, 
    count(*) N_Viagens 
from masterTable 
group by month(date_hour), passenger, airline, nationality, passport 
having count(*) > 10 

рядом есть код, чтобы создать таблицу, но я не могу изменить этот код, только запрос или создание индексов:

select 
p.birthdate, p.gender, p.passport, p.name + ' ' + p.surname passenger, p.nationality, 
    r.class, r.flightNR, r.payment, r.ticketNR, 
    f.src_AP_ID, f.dest_AP_ID, f.AL_ID, f.date_hour, f.AirCrft_Code,ac.manufacturer, ac.model, 
    SA.City 'Origin City', SA.Country 'Origin Country', SA.Name 'Origin Airport', 
    DA.City 'Dest City', DA.Country 'Dest Country', DA.Name 'Dest Airport', 
    al.Name airline, al.IATA, al.icao 
into masterTable 
from passenger p 
join reservation r on r.passport = p.passport 
join flight f on f.flightNR = r.flightNR 
join airport SA on f.src_AP_ID = SA.AP_Id 
join airport DA on f.dest_AP_ID = DA.AP_Id 
join aircraft ac on f.airCrft_Code = ac.code 
join airline al on f.AL_ID = al.AL_ID 

без индекса:

SQL Server Execution Times: CPU time = 10125 ms, elapsed time = 17052 ms. 

ЛЮДИ Я думаю, что я сделал это, спасибо всем, спасибо СНОВА

Я создал индекс, как это:

create index idx_MasterTable_Passenger on masterTable(passport, airline) 

и запрос я изменил к этому:

select month(date_hour), max(passenger) as passenger, nationality, passport, airline, count(*) N_Viagens 
from masterTable 
group by airline, nationality, passport, month(date_hour) 
having count(*) > 10 

Что вы думаете, приемлемо ли это?

SQL Server Execution Times: CPU time = 8362 ms, elapsed time = 5721 ms. 

Я буду говорить с учителем, если он согласен с этим

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

+3

'GROUP BY month (date_hour)'? Так что вам все равно, будет ли счет прибыть с ноября 2000 года или ноября 2011 года или в любой другой год, просто бросьте их всех в одно и то же ведро? –

+0

И добавление индекса на Natural Key (пассажир, авиакомпания, национальность) наверняка ускорит процесс. Он будет делать вставки медленнее, но быстрее выбирает – MikeTWebb

+0

Это было дано моим профессором так же, как и я, моя работа - быстро его превратить –

ответ

0

Появляется паспорт лучше идентификатор, чем имя. Разрешите, чтобы человек изменил свое имя.

Создать индекс по паспорту, авиакомпания

Вы можете расширить индекс гражданства, паспорта, авиакомпании, пассажир, но не уверен, сколько, что вы покупаете вы?

select nationality, passport, airline, year(date_hour), month(date_hour), max(passenger), count(*) N_Viagens 
from masterTable 
group by nationality, passport, airline, year(date_hour), month(date_hour) 
having count(*) > 10 
+0

WAIT .... Я сделал это и время выполнения SQL Server: Время процессора = 9595 мс, прошедшее время = 6490 мс .... и он показывает результаты 30949 ..... hummm, но я думаю –

+0

heheheh я сделал это, что-то вроде глупого lol, но он работает, я отредактировал запрос, который у меня был к этому: 'select month (date_hour), max (пассажир), национальность, паспорт, авиакомпания, счет (*) N_Viagens от masterTable (*)> 10' и время: 'Время выполнения SQL Server: Время процессора = 8315 мс, прошедшее время = 5765 ms.' –

+0

извините, я делал это сейчас, я новый здесь, я зарегистрировался сегодня, извините, но вы правы в этом году, не имеет смысла –

0

Что содержит MasterTable? Похоже, что это будет содержать что-то вроде сегментов полета для пассажиров. Если это так, очень немногие пассажиры летают более 10 раз в месяц.

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

(1) Построить индекс на пассажира в MasterTable:

create index idx_MasterTable_Passenger on MasterTable(Passenger); 

(2) Признать, что люди, которые летают в 10 раз являются редкими по отношению ко всем остальным, поэтому отфильтруйте их:

select month(date_hour), passenger, nationality, passport, airline, 
     count(*) as N_Viagens 
from masterTable 
where passenger in (select passenger from MasterTable group by passenger having count(*) >= 10) 
group by month(date_hour), passenger, airline, nationality, passport 
having count(*) > 10 

Это может ускорить запрос.

Однако я бы предложил что-то другое. Создайте таблицу, которая суммирует информацию на пассажире (или на каком-то подобном уровне), чтобы ответить на такие вопросы. Когда новые данные добавляются в основную таблицу, обновите или вставьте строки в эту таблицу.

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

+0

Время выполнения SQL Server: Время процессора = 11560 мс, прошедшее время = 18903 мс. Это дает мне больше времени, это странно Я делаю что-то неправильно? Я запустил первый запрос для создания индекса, затем запустил второй запрос, как он есть здесь, скопируйте + вставить, и время больше: S –

+0

Я не согласен с людьми, которые пролетели 10 раз в любой авиакомпании за все месяцы редко. Большинство из них, которые имеют поток, пролетели 10 раз в жизни. 10 раз за один месяц в одной авиакомпании WAY отличается от 10 раз. – Paparazzi

0

Этот запрос всегда требует сканирования. Теперь есть предложение WHERE, поэтому мы не можем ускорить запрос, быстро изолируя меньшее подмножество. Существует предложение HAVING, но оно может применяться только после агрегации.

Однако существует предложение GROUP BY; агрегация в предложении GROUP BY может ускоряться путем добавления соответствующего индекса.Поскольку столбцы из предложения GROUP BY также используются в списке SELECT, мы можем добиться того, что нужно сканировать только этот индекс, а не всю таблицу.

Предложение GROUP BY содержит выражение month (date_hour). Это означает, что мы можем игнорировать это для индекса. Остается пассажир, авиакомпания, гражданство, паспорт. Перед созданием индекса вам нужно выяснить правильный порядок. Моя догадка заключается в том, что вам нужно сначала поставить наиболее избирательные столбцы - то есть столбцы с наибольшим количеством уникальных значений должны появиться перед теми, у которых есть небольшое количество уникальных значений. Я бы предположил, что заказ пассажира, авиакомпании, гражданства, паспорта уже очень хорош. Тем не менее, я бы немного экспериментировал, изменив порядок столбцов.

Как только вы создали индекс, вам не придется переписывать запрос. Однако, если оптимизатор вашей РСУБД наивен (например, MySQL), вам нужно будет поместить выражение month (date_hour) в качестве последнего выражения предложения GROUP BY. Это никак не изменит результат, хотя это может повлиять на порядок, в который возвращаются строки. Однако это не должно иметь значения (и если это так, вы должны добавить предложение ORDER BY)

+0

_ "... выражение month (date_hour). Это означает, что мы можем игнорировать это для индекса." _ Если СУБД не поддерживает функциональные индексы, которые делает MS SQL. Кроме того, порядок в GROUP BY имеет значение. Хотя конец 'month (date_hour)' в конце будет способствовать производительности (при отсутствии соответствующего функционального индекса), это также изменит смысл запроса. ОП будет решать, будет ли это изменение приемлемым. –

+1

«Кроме того, заказ в GROUP BY имеет значение».

+1

Вы правы. Я думаю, что могут быть различия для ROLLUP и т. Д., Но это не имеет значения в данном конкретном случае. –

1

Это сложный вопрос - чтобы действительно ускорить группировку на month(date_hour), вам понадобится индекс (aka index on a computed column в MS SQL Server) на это точное выражение. Просто иметь индекс на date_hour не достаточно.

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

Поскольку это домашнее задание, я позволю вам включить это в свой пример.

Кстати, если вы заинтересованы в теме индексов и производительности, я горячо рекомендую читать: Use The Index, Luke!

+1

Это лучший подход, если важна производительность. Индекс должен быть на всех 5 столбцах (4 «обычных» и 1 вычисленных): '(the_month, пассажир, авиакомпания, национальность, паспорт)' –

+0

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

+0

@DaniSilva Ну, это зависит от того, как вы определяете «изменение таблицы». Создавая вычисленный столбец, вы не меняете физические данные таблицы каким-либо образом. В этом контексте вычисленный столбец является просто вспомогательным механизмом для индексирования. –

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