针对大型查询优化MySql数据库

时间:2013-03-18 20:48:30

标签: mysql optimization query-optimization performance-testing

我正在构建一个大型数据库。我的一张桌子有300K记录,另一张有500万张记录。 我目前拥有所有外键和名为“ph.trigger_on”的列索引。

我的问题是如何优化我的表/查询以获得更快的结果?我尝试使用此代码创建一个视图,然后从此视图中,我可以获得查询此视图时所需的所有信息。

通过查询仍然很慢,我很难理解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)

我可以做些什么来改善我的表格或查询。

1 个答案:

答案 0 :(得分: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个连接推入SELECT部分​​。