我有一个 mySQL 表 (myISAM),其中包含大约 200 万行 - 姓名、地址、公司数据。名字和姓氏分别保存在不同的列中,因此我还有第二个表(由第一个表的主键链接),其中包含一个全名列。
第一个表中的名字、姓氏和公司名称(以及其他)被索引,辅助表中的全名列也是如此。
以此查询为起点:
SELECT * FROM table_a INNER JOIN table_b ON table_a.ID = table_b.ID WHERE....
在名称列上搜索完全匹配甚至类似之后的工作以毫秒为单位:
....table_a.first_name = 'Fred'
....table_a.surname = 'Bloggs'
....table_b.fullname = 'Fred Bloggs'
....table_a.first_name LIKE 'Mike%'
只是几个例子。
将公司名称也扔在那里......查询突然需要 15 到 20 秒:
....table_a.first_name = 'Fred' OR table_a.company_name = 'Widgets Inc'
例如
两个字段都被索引,这是一个完全匹配......为什么添加第二个索引搜索列会减慢速度?我错过了关于我的桌子设计的一些东西吗?
示例如下 - 加入了一些其他表,但我不确定这些是否会影响性能:在 0.0123 秒内返回的仅名称查询示例:
SELECT SQL_CALC_FOUND_ROWS
webmaster.dupe_master_id AS webmaster_id,
webmaster.first_name,
webmaster.family_name,
webmaster.job_title,
webmaster.company_name,
webmaster.address_1,
webmaster.address_2,
webmaster.town_city,
webmaster.state_county,
webmaster.post_code,
webmaster.email,
webmaster.ignored,
countries.country_name,
GROUP_CONCAT(DISTINCT titles.code ORDER BY code ASC) AS sub_string,
'' AS expo_string
FROM
(`webmaster`)
LEFT JOIN `countries` ON `countries`.`country_id` = `webmaster`.`country_id`
LEFT JOIN `red_subscriptions` ON `red_subscriptions`.`webmaster_id` = `webmaster`.`webmaster_id` AND red_subscriptions.subscription_status_id = 2
LEFT JOIN `titles` ON `titles`.`title_id` = `red_subscriptions`.`title_id`
LEFT JOIN `webmaster_tags` ON `webmaster_tags`.`webmaster_id` = `webmaster`.`webmaster_id`
LEFT JOIN `tags` ON `tags`.`tag_id` = `webmaster_tags`.`tag_id`
INNER JOIN `webmaster_search_data` ON `webmaster`.`webmaster_id` = `webmaster_search_data`.`webmaster_id`
WHERE
(full_name = '<name>')
GROUP BY
`webmaster`.`dupe_master_id`
LIMIT 50
添加 company_name (也被索引),查询时间通过屋顶:
SELECT SQL_CALC_FOUND_ROWS
webmaster.dupe_master_id AS webmaster_id,
webmaster.first_name,
webmaster.family_name,
webmaster.job_title,
webmaster.company_name,
webmaster.address_1,
webmaster.address_2,
webmaster.town_city,
webmaster.state_county,
webmaster.post_code,
webmaster.email,
webmaster.ignored,
countries.country_name,
GROUP_CONCAT(DISTINCT titles.code ORDER BY code ASC) AS sub_string,
'' AS expo_string
FROM
(`webmaster`)
LEFT JOIN `countries` ON `countries`.`country_id` = `webmaster`.`country_id`
LEFT JOIN `red_subscriptions` ON `red_subscriptions`.`webmaster_id` = `webmaster`.`webmaster_id` AND red_subscriptions.subscription_status_id = 2
LEFT JOIN `titles` ON `titles`.`title_id` = `red_subscriptions`.`title_id`
LEFT JOIN `webmaster_tags` ON `webmaster_tags`.`webmaster_id` = `webmaster`.`webmaster_id`
LEFT JOIN `tags` ON `tags`.`tag_id` = `webmaster_tags`.`tag_id`
INNER JOIN `webmaster_search_data` ON `webmaster`.`webmaster_id` = `webmaster_search_data`.`webmaster_id`
WHERE
(full_name = '<name>' OR company_name '<name>')
GROUP BY
`webmaster`.`dupe_master_id`
LIMIT 50
仅对全名进行解释:
id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE webmaster_search_data ref webmaster_id,full_name full_name 302 const 94 使用where; 使用临时的;使用文件排序 1 SIMPLE webmaster eq_ref PRIMARY PRIMARY 4 webmaster_search_data.webmaster_id 1
1 SIMPLE countries eq_ref PRIMARY PRIMARY 2 webmaster.country_id 1
1 SIMPLE red_subscriptions ref webmaster_id,subscription_status_id webmaster_id 4 webmaster_search_data.webmaster_id 1 1
SIMPLE
title eq_ref PRIMARY PRIMARY 1 title SIMDLE
webmaster_tags ref webmaster_id webmaster_id 4 webmaster_search_data.webmaster_id 5
1 简单标签 eq_ref PRIMARY PRIMARY 2 webmaster_tags.tag_id 1 使用索引
说明何时添加 company_name:
1 SIMPLE webmaster index PRIMARY,company_name dupe_master_id 4 NULL 2072015 使用文件排序 1 SIMPLE 国家 eq_ref PRIMARY PRIMARY 2 webmaster.country_id 1
1 SIMPLE red_subscriptions ref webmaster_id,subscription_status_id webmaster_id 4 webmaster.webmaster_id 1 1
SIMPLE
title eq_ref PRIM_ARY PRIMARY 2 red_PIMARY 标题 2
webmaster_tags ref webmaster_id webmaster_id 4 webmaster.webmaster_id 5
1 SIMPLE tags eq_ref PRIMARY PRIMARY 2 webmaster_tags.tag_id 1 使用索引 1 SIMPLE webmaster_search_data eq_ref webmaster_id,full_name webmaster_id 4 webmaster.webmaster_id 1 使用where