1

Я создаю большую базу данных. одна из моих таблиц имеет 300 тыс. записей, а другая - 5 миллионов записей. В настоящее время у меня есть все внешние ключи и столбцы с именем «ph.trigger_on», индексированные.Оптимизация базы данных MySql для больших запросов

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

По запросу все еще медленно, и у меня возникают трудности с пониманием результатов, которые показывает EXPLAIN. Это мой текущий запрос

EXPLAIN SELECT 
ac.account_name AS accountName, 
tm.name AS teamName, 
cp.name AS campaignName, 
cc.call_code_name AS callCode, 
rc.result_code_name AS resultCode, 
zn.name AS zoneName, 
ind.name AS industry, 
(su.first_name + su.middle_name + su.last_name) AS owner_name, 
su.login_user AS ownerLoginUser, 
(su1.first_name + su1.middle_name + su1.last_name) AS firstAttemptBy, 
(su2.first_name + su2.middle_name + su2.last_name) AS lastAttemptBy, 
(su3.first_name + su3.middle_name + su.last_name) AS modifiedBy, 
ci.name AS clientName, 
ph.trigger_on AS triggerOn, 
ph.created_on AS createdOn, 
ph.first_attempt_on AS firstAttemptOn, 
ph.call_subject AS callSubject, 
ph.status, 
ph.last_attempt_on AS lastAttemptOn, 
ph.total_attempts AS totalAttempts, 
ph.call_direction AS callDirection, 
ph.call_notes AS callNotes, 
ph.call_duration AS callDuration, 
ph.modified_on AS modifiedOn 

FROM phone_calls AS ph 
INNER JOIN accounts AS ac ON ph.account_id = ac.account_id 
INNER JOIN clients AS ci ON ac.client_id = ci.client_id 
INNER JOIN industries AS ind ON ac.industry_id = ind.industry_id 
INNER JOIN call_codes AS cc ON ph.call_code_id = cc.call_code_id 
INNER JOIN time_zones AS zn ON ph.time_zone_id = zn.time_zone_id 
INNER JOIN users AS su ON ph.owner_id = su.user_id 

LEFT JOIN teams AS tm ON ph.team_id = tm.team_id 
LEFT JOIN result_codes AS rc ON ph.result_code_id = rc.result_code_id 
LEFT JOIN campaigns AS cp ON ph.campaign_id = cp.campaign_id 
LEFT JOIN users AS su1 ON ph.first_attempt_by = su1.user_id 
LEFT JOIN users AS su2 ON ph.last_attempt_by = su2.user_id 
LEFT JOIN users AS su3 ON ph.modified_by = su3.user_id 
WHERE ph.trigger_on < now() 
LIMIT 1000 

это мой выходной ток.

id select_type table type possible_keys key key_len ref rows Extra 
1 SIMPLE ci ALL PRIMARY    1 
1 SIMPLE zn ALL PRIMARY    1 Using join buffer (Block Nested Loop) 
1 SIMPLE su ALL PRIMARY    1 Using join buffer (Block Nested Loop) 
1 SIMPLE ac ref PRIMARY,client_id,industry_id client_id 4 rdi_cms.ci.client_id 95917 
1 SIMPLE ind eq_ref PRIMARY PRIMARY 4 rdi_cms.ac.industry_id 1 
1 SIMPLE ph ref owner_id,call_code_id,account_id,time_zone_id,trigger_on account_id 4 rdi_cms.ac.account_id 11 Using where 
1 SIMPLE tm ALL PRIMARY    1 Using where; Using join buffer (Block Nested Loop) 
1 SIMPLE rc eq_ref PRIMARY PRIMARY 4 rdi_cms.ph.result_code_id 1 
1 SIMPLE cc eq_ref PRIMARY PRIMARY 4 rdi_cms.ph.call_code_id 1 
1 SIMPLE cp ALL PRIMARY    1 Using where; Using join buffer (Block Nested Loop) 
1 SIMPLE su1 ALL PRIMARY    1 Using where; Using join buffer (Block Nested Loop) 
1 SIMPLE su2 ALL PRIMARY    1 Using where; Using join buffer (Block Nested Loop) 
1 SIMPLE su3 ALL PRIMARY    1 Using where; Using join buffer (Block Nested Loop) 

Что я могу сделать, чтобы улучшить свои таблицы или мой запрос.

+0

Главное, чтобы все поля условий были проиндексированы: все поля JOIN ON и все поля WHERE. Я не думаю, что многое другое вы можете сделать, присоединившись к 13 (!!) таблицам ... Вам действительно нужны 12 присоединяться? Если какая-то часть просто ограничивает результаты, вы можете попробовать это в отдельном запросе. ** Иногда ** это быстрее (кеш запросов!), Если вы создаете несколько небольших запросов. – Rudie

+0

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

+0

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

ответ

2

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

SELECT 
ac.account_name AS accountName, 
tm.name AS teamName, 
cp.name AS campaignName, 
cc.call_code_name AS callCode, 
rc.result_code_name AS resultCode, 
(SELECT zn.name FROM time_zones AS zn WHERE ph.time_zone_id = zn.time_zone_id) AS zoneName, 
(SELECT ind.name FROM industries AS ind WHERE ac.industry_id = ind.industry_id) AS industry, 
(SELECT su.first_name + su.middle_name + su.last_name users AS su WHERE ph.owner_id = su.user_id) AS owner_name, 
su.login_user AS ownerLoginUser, 
(su1.first_name + su1.middle_name + su1.last_name) AS firstAttemptBy, 
(su2.first_name + su2.middle_name + su2.last_name) AS lastAttemptBy, 
(su3.first_name + su3.middle_name + su.last_name) AS modifiedBy, 
ci.name AS clientName, 
ph.trigger_on AS triggerOn, 
ph.created_on AS createdOn, 
ph.first_attempt_on AS firstAttemptOn, 
ph.call_subject AS callSubject, 
ph.status, 
ph.last_attempt_on AS lastAttemptOn, 
ph.total_attempts AS totalAttempts, 
ph.call_direction AS callDirection, 
ph.call_notes AS callNotes, 
ph.call_duration AS callDuration, 
ph.modified_on AS modifiedOn 

FROM phone_calls AS ph 
INNER JOIN accounts AS ac ON ph.account_id = ac.account_id 
INNER JOIN clients AS ci ON ac.client_id = ci.client_id 
INNER JOIN call_codes AS cc ON ph.call_code_id = cc.call_code_id 
INNER JOIN time_zones AS zn ON ph.time_zone_id = zn.time_zone_id 

LEFT JOIN teams AS tm ON ph.team_id = tm.team_id 
LEFT JOIN result_codes AS rc ON ph.result_code_id = rc.result_code_id 
LEFT JOIN campaigns AS cp ON ph.campaign_id = cp.campaign_id 
LEFT JOIN users AS su1 ON ph.first_attempt_by = su1.user_id 
LEFT JOIN users AS su2 ON ph.last_attempt_by = su2.user_id 
LEFT JOIN users AS su3 ON ph.modified_by = su3.user_id 
WHERE ph.trigger_on < now() 
LIMIT 1000 

здесь я толкнул 3 присоединяется к селектам части.

+0

Поскольку фильтр не нуждается в этих объединениях? Это своего рода умный ... – Rudie

+0

Я не вижу, что вы сделали с моим запросом, другим, удалив 2 соединения, которые мне нужны. – Jaylen

+0

Я НЕ УДАЛЯЛ их! я просто переместил их в более позднее состояние исполнения. – ITroubs

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