2014-02-17 1 views
0

Здравствуйте, снова хорошие люди Stackoverflow. Основываясь на нескольких ответах на подобные вопросы, я полагаю, что добавление индексов в мои таблицы поможет выполнить запрос ниже. Задача состоит в том, что я не слишком хорошо знаком или удобен с использованием индексов, поскольку, по-видимому, существует потенциал замедления других запросов при использовании слишком большого количества индексов. Просто найдите кого-то, кто поможет мне в правильном направлении. Заранее благодарю за помощь.MySql, индексирование и ускорение запроса

Запрос:

SELECT 
    territories.territoryID, 
    territories.territory_name, 
    territories_meta.tm_color, 
    territories.territory_description, 
    territories.territory_state, 
    GROUP_CONCAT(distinct(territories_zips.tz_zip)SEPARATOR ', ') AS ZipCodes, 
    count(distinct(users.userID)) as AgentsAssigned, 
    GROUP_CONCAT(distinct(concat(users.user_Fname,' ',users.user_Lname))SEPARATOR ', ') 
     AS AgentName, 
    a.sumTerr as TotalOpp 
from(
    SELECT 
     territories_zips.tz_terrID as terrID, 
     sum(boundaries_meta.bm_opportunity) as sumTerr 
    FROM territories_zips 
    INNER JOIN boundaries ON boundaries.boundary_name = territories_zips.tz_zip 
    INNER JOIN boundaries_meta ON boundaries.boundary_id = boundaries_meta.bm_boundariesID 
    where tz_status = 1 
    group by tz_terrID 
)as a 
inner join territories on territories.territoryID = a.terrId 
INNER JOIN territories_zips ON territories.territoryID = territories_zips.tz_terrID 
INNER JOIN territories_assign ON territories.territoryID = territories_assign.ta_territoryID 
INNER JOIN users ON users.userID = territories_assign.ta_repID 
INNER JOIN territories_meta ON territories_meta.tm_territoryID = territories.territoryID 
WHERE 
    territories_zips.tz_status = 1 AND 
    territories_assign.ta_repStatus = 1 AND 
    users.user_status = 1 
GROUP BY territoryID 

Объясните:

id select_type table typw possible_keys key key_len ref rows extra 
1 PRIMARY <derived2> ALL     97 Using temporary; Using filesort 
1 PRIMARY territories_meta ALL     121 Using where; Using join buffer 
1 PRIMARY territories_zips ALL     1739 Using where; Using join buffer 
1 PRIMARY territories_assign ALL     138 Using where; Using join buffer 
1 PRIMARY users eq_ref PRIMARY PRIMARY 8 msb_db.territories_assign.ta_repID 1 Using where 
1 PRIMARY territories eq_ref PRIMARY PRIMARY 8 msb_db.territories_meta.tm_territoryID 1 Using where 
2 DERIVED territories_zips ALL     1739 Using where; Using temporary; Using filesort 
2 DERIVED boundaries_meta ALL     42995 Using join buffer 
2 DERIVED boundaries eq_ref PRIMARY PRIMARY 4 msb_db.boundaries_meta.bm_boundariesID 1 Using where 

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

SELECT 
    territories_zips.tz_terrID as terrID, 
    sum(boundaries_meta.bm_opportunity) as sumTerr 
FROM territories_zips 
INNER JOIN boundaries ON boundaries.boundary_name = territories_zips.tz_zip 
INNER JOIN boundaries_meta ON boundaries.boundary_id = boundaries_meta.bm_boundariesID 
where tz_status = 1 
group by tz_terrID 

и это объясняет:

id select_type table typw possible_keys key key_len ref rows extra 
1 SIMPLE territories_zips ALL     1739 Using where; Using temporary; Using filesort 
1 SIMPLE boundaries_meta ALL     42995 Using join buffer 
1 SIMPLE boundaries eq_ref PRIMARY PRIMARY 4 mb_db.boundaries_meta.bm_boundariesID 1 Using where 

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

Таблицы:

CREATE TABLE `boundaries` (
     `boundary_id` int(11) NOT NULL AUTO_INCREMENT, 
    `boundary_name` varchar(20) DEFAULT NULL, 
    `geometry_type` varchar(12) DEFAULT NULL, 
    `boundary_geometry` mediumtext, 
    `boundary_type` varchar(5) DEFAULT NULL, 
    `boundary_state` varchar(4) DEFAULT NULL, 
    PRIMARY KEY (`boundary_id`) 
) ENGINE=MyISAM AUTO_INCREMENT=64504 DEFAULT CHARSET=utf8; 

CREATE TABLE `boundaries_meta` (
    `boundaries_metaID` bigint(20) NOT NULL AUTO_INCREMENT, 
    `bm_boundariesID` bigint(20) NOT NULL, 
    `bm_opportunity` int(5) NOT NULL, 
    PRIMARY KEY (`boundaries_metaID`) 
) ENGINE=MyISAM AUTO_INCREMENT=51201 DEFAULT CHARSET=utf8; 


CREATE TABLE `territories_zips` (
    `terr_zipsID` bigint(10) NOT NULL AUTO_INCREMENT, 
`tz_terrID` bigint(10) NOT NULL, 
`tz_zip` varchar(5) CHARACTER SET latin1 NOT NULL, 
`tz_status` smallint(1) NOT NULL, 
PRIMARY KEY (`terr_zipsID`) 
) ENGINE=MyISAM AUTO_INCREMENT=2576 DEFAULT CHARSET=utf8; 

Еще раз благодарю вас за помощь.

EDIT: Я обновил некоторые таблицы с индексами и получил невероятное улучшение (еще раз спасибо королю Исааку). Я включаю новое объяснение в подзапрос, поскольку мне все еще не нравится, как и почему это помогло, или если я действительно создал индексы в правильных частях. Дайте человеку рыбу, он съедает за день, научи его ловить рыбу, и ....

id select_type table type possible keys key key_len ref rows extra 
1 SIMPLE territories_zips ALL     1739  Using where; Using temporary; Using filesort 
1 SIMPLE boundaries ref PRIMARY,bndIDindex,bndNameindex bndNameindex 63 func 1 Using where 
1 SIMPLE boundaries_meta eq_ref bmBndIDindex bmBndIDindex 8 mb_db.boundaries.boundary_id 1 Using where 

ответ

1

Похоже, ваш первый шаг будет обрабатывать tz_zip и boundary_name присоединиться. Мой первый вопрос: были ли они уникальными? Применение индекса UNIQUE к этим таблицам должно значительно ускорить ваш подзапрос. Если они не будут уникальными, то стандартный индекс по-прежнему будет предоставлять вам достаточно высокую мощность, чтобы увидеть увеличение скорости.

Поля «status» на всех таблицах также должны быть проиндексированы. Несмотря на то, что в конечном итоге они будут низкими показателями мощности, это принесет пользу запросу, не вызывая значительных накладных расходов.

Вы также можете посмотреть, можете ли вы реорганизовать этот запрос, чтобы исключить подзапрос в предложении 'from'. Это заставляет весь запрос зависеть от временной таблицы, которая должна быть полностью установлена ​​до того, как процесс запроса будет продолжен. Я бы вышел на конечность и сказал, что это также причина того, что вы видите так много типов «ВСЕ». Анализатор запросов не может работать с подмножеством данных, поэтому он выполняет полное сканирование таблицы. Это плохо, когда это происходит с одним столом, в вашем случае это происходит до пяти.

Я бы посмотрел на обработку boundary_meta как на простое соединение и обработку SUM(boundaries_meta.bm_opportunity) в SELECT. Возможно, это должен быть зависимый подзапрос, но вы все равно должны видеть увеличение производительности.

Что касается вашего страха относительно скорости индекса: чрезмерная индексация может быть проблемой при добавлении нескольких индексов в таблицу, но в целом это не проблема, если вы не индексируете несколько столбцов на основе символов.Поскольку мы говорим только о двух столбцах varchar(5), это не должно быть проблемой.

Независимо от того, следует ли индексировать столбец, всегда является вопросом цены/выгоды. Стоимость измеряется по размеру, а прибыль может быть измерена в мощности.

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

+0

Спасибо, королю Исааку. Очень тщательный обзор, я с нетерпением жду, чтобы копаться в ваших очках и скоро вернусь с некоторыми ответами и, вероятно, с большим количеством вопросов. – alex

+0

В отношении первого вопроса: tz_zip и имя_границы не уникальны. Я не совсем уверен, что такое стандартный индекс или как я могу применить его в этом случае к любому из двух. Теперь я рассмотрю суб-запрос. Еще раз спасибо – alex

+0

Конечно, вам стоит поставить уникальный индекс, где вы можете. Под «стандартным индексом» я имел в виду тот, который можно просто добавить через «ALTER TABLE ADD INDEX». http://dev.mysql.com/doc/refman/5.1/en/alter-table.html –