2013-06-27 2 views
8

У меня есть следующая структура базы данных:Как ускорить sql-запросы? Индексы?

create table Accounting 
(
    Channel, 
    Account 
) 

create table ChannelMapper 
(
    AccountingChannel, 
    ShipmentsMarketPlace, 
    ShipmentsChannel 
) 

create table AccountMapper 
(
    AccountingAccount, 
    ShipmentsComponent 
) 

create table Shipments 
(
    MarketPlace, 
    Component, 
    ProductGroup, 
    ShipmentChannel, 
    Amount 
) 

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

select Accounting.Channel, Accounting.Account, Shipments.MarketPlace 
from Accounting join ChannelMapper on Accounting.Channel = ChannelMapper.AccountingChannel 

join AccountMapper on Accounting.Accounting = ChannelMapper.AccountingAccount 
join Shipments on 
(
    ChannelMapper.ShipmentsMarketPlace = Shipments.MarketPlace 
    and ChannelMapper.AccountingChannel = Shipments.ShipmentChannel 
    and AccountMapper.ShipmentsComponent = Shipments.Component 
) 
join (select Component, sum(amount) from Shipment group by component) as Totals 
    on Shipment.Component = Totals.Component 

Как Я запускаю этот запрос как можно быстрее? Должен ли я использовать индексы? Если да, то в каких столбцах таблицы следует индексировать?

Вот фотография моего плана запроса:

enter image description here

Спасибо,

enter image description here

+2

Индексы необходимы. Все, что содержится в предложении WHERE, является кандидатом на индексирование. Можете ли вы опубликовать фактическую схему вместо своей абстрактной версии? – tadman

+0

Моделирование данных имеет решающее значение. Во-первых: добавьте в свои столбцы некоторые реальные типы (возможно, домены). Второе: ограничения PK/FK являются элементарными. В-третьих: (как правило, если в таблицах имеется более двух ключей-кандидатов, они подозреваются. Ваши таблицы каналов и отправлений _could_ страдают от этого явления (могут быть BCNF или 4NF vioalations), но вы не показывали никаких ключей-кандидатов, и даже семантика нечеткая. – wildplasser

ответ

18

Индексы необходимы для любой базы данных.

Говоря в терминах «непрофессионала», индексы ... ну, именно это. Вы можете представить индекс как вторую, скрытую таблицу, которая хранит две вещи: отсортированные данные и указатель на ее позицию в таблице.

Некоторые правила большого пальца на создание индексов:

  1. Создание индексов на каждом поле, которое (или будет) использоваться в соединениях.
  2. Создание индексов на каждом поле, на котором вы хотите часто выполнять where условий.
  3. Избегайте создания индексов на все. Создайте индекс в соответствующих полях каждой таблицы и используйте отношения для извлечения желаемых данных.
  4. Избегайте создания индексов на double полях, если это абсолютно необходимо.
  5. Избегайте создания индексов на varchar полях, если только это не является абсолютно необходимым.

Я рекомендую вам прочитать: http://dev.mysql.com/doc/refman/5.5/en/using-explain.html

+3

Индексы на парных и варшарах прекрасны, когда они актуальны. Мы находимся в 2013 году, а не в 1980-х годах. –

+0

@Denis Это хороший момент. Я избегаю их, потому что я вообще могу использовать другие индексированные поля и получать те же результаты. (Кстати, я не *, что * old ;-)) – Barranka

3

Ваш JOINS должен быть первым местом для поиска. Двумя наиболее очевидными кандидатами для индексов являются AccountMapper.AccountingAccount и ChannelMapper.AccountingChannel.

Вы должны рассмотреть возможность индексации Shipments.MarketPlace, Shipments.ShipmentChannel и Shipments.Component.

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

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

2

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

У вас также есть это:

join (select Component, sum(amount) from Shipment group by component) as Totals 
on Shipment.Component = Totals.Component 

Это все хорошо и хорошо, но ты ничего из этого подзапроса не выбрать. Поэтому почему у вас это есть? Если вы хотите что-то выбрать, например сумму (сумму), вам нужно будет указать псевдоним, чтобы сделать его доступным в предложении select.