Примечание: SQL Server - это то, что я использую. Если вы используете что-то другое - это может не применяться.
Также обратите внимание: я собираюсь обсудить индексы, чтобы помочь в доступе к данным из таблицы. Индексы покрытия - это отдельная тема, к которой я не обращаюсь.
При доступе к таблице есть 3 способа сделать это.
- Использовать критерии фильтрации.
- Использовать реляционные критерии из уже прочитанных строк.
- Прочитайте всю таблицу!
Я начал с составления списка всех таблиц с критериями фильтрации и реляционными критериями.
articles
articles.expirydate > 'somedate'
articles.dateadded > 'somedate'
articles.status >= someint
articles.article_id <-> articles_to_geo.article_id
articles.article_id <-> articles_to_badges.article_id
articles.site_id <-> sites.id
articles_to_geo
articles_to_geo.article_id <-> articles.article_id
articles_to_geo.whitelist_city_id <-> cities_whitelist.city_id
cities_whitelist
cities_whitelist.published = someint
cities_whitelist.city_id <-> articles_to_geo.whitelist_city_id
cities_whiltelist.city_id <-> cities.city_id
cities
cities.city_id <-> cities_whiltelist.city_id
articles_to_badges
articles_to_badges.badge_id in (some ids)
articles_to_badges.article_id <-> articles.article_id
article_to_badges.badge_id <-> badges.id
badges
badges.id <-> article_to_badges.badge_id
sites
sites.id <-> articles.site_id
Самый неуклюжий способ подойти к этому - просто создать индекс для каждой таблицы, поддерживающей каждый реляционный и фильтрующий критерии ..., а затем позволить оптимизатору выбрать, какие индексы он хочет использовать. Этот подход хорош для производительности ввода-вывода и прост в реализации ... но он занимает много места в неиспользуемых индексах.
Следующий лучший способ - запустить запрос с включенными параметрами:
SET STATISTICS IO ON
SET STATISTICS TIME ON
Если в конкретном наборе таблиц используется больше операций ввода-вывода, усилия по индексированию могут быть сосредоточены на них. Для этого необходимо, чтобы план оптимизатора для порядка доступа к таблицам уже был достаточно хорошим.
Если оптимизатор вообще не может составить хороший план из-за отсутствия индексов, я выясняю, в каком порядке я хотел бы получить доступ к таблицам, а затем добавляю индексы, поддерживающие такой доступ.
Примечание: первая доступная таблица не имеет возможности использовать реляционные критерии, поскольку записи еще не прочитаны. Первая таблица должна быть доступна с помощью критериев фильтрации или чтения всей таблицы.
Одним из возможных заказов является заказ в запросе. Этот подход может быть довольно плохим, потому что наши критерии фильтрации статей основаны на 3 различных диапазонах. Могут быть тысячи статей, которые соответствуют этим критериям, и трудно составить индекс для поддержки этих диапазонов.
Articles (Filter)
Articles_to_Geo (Relational by Article_Id)
Cities_WhiteList (Relational by City_Id) (Filter)
Cities (Relational by City_Id) (Filter)
Articles_to_Badges (Relational by Article_Id) (Filter)
Badges (Relational by Badge_Id)
Sites (Relational by Article_Id)
Другой возможный заказ - сначала Города. Критерии для городов легко индексируются, и их может быть только 1 строка! При поиске статей для города и последующей фильтрации по дате следует прочитать меньше строк, чем при поиске статей по датам, а затем выполнить фильтрацию по городу.
Cities (Filter)
Cities_WhiteList (Relational by City_Id) (Filter)
Articles_to_Geo (Relational by City_Id)
Articles (Relational by Article_Id) (Filter)
Articles_to_Badges (Relational by Article_Id) (Filter)
Badges (Relational by Badge_Id)
Sites (Relational by Article_Id)
Третий подход - сначала бейджи. Это было бы лучше, если бы в статьях редко накапливались значки, а значков не было.
Badges (Read the Whole Table)
Articles_to_Badges (Relational by Badge_Id) (Filter)
Articles (Relational by Article_Id) (Filter)
Articles_to_Geo (Relational by Article_Id)
Cities_WhiteList (Relational by City_Id) (Filter)
Cities (Relational by City_Id) (Filter)
Sites (Relational by Article_Id)