Sur*_*dhu 3 mysql performance count mysql-5.5 query-performance
我有以下查询需要 7 秒才能运行
SELECT COUNT(*) AS `count`
FROM `yuldi`.`businesses` AS `Business`
LEFT JOIN `yuldi`.`businesses_categories` AS `BusinessesCategory`
ON (`Business`.`id` = `BusinessesCategory`.`business_id`)
LEFT JOIN `yuldi`.`categories` AS `Category`
ON (`BusinessesCategory`.`category_id` = `Category`.`id`)
WHERE `Category`.`slug` = 'building-construction'
Run Code Online (Sandbox Code Playgroud)
当我第二次运行它时需要 160 毫秒。为什么每次第一次运行都需要这么长时间
解释:
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
| 1 | SIMPLE | Category | const | PRIMARY,UNIQUE_SLUG,index_lug | UNIQUE_SLUG | 302 | const | 1 | Using index |
| 1 | SIMPLE | BusinessesCategory | ref | PRIMARY,fk_businesses_has_categories_categories1_idx,fk_businesses_has_categorie_businesses_idx | fk_businesses_has_categories_categories1_idx | 4 | const | 49630 | Using where; Using index |
| 1 | SIMPLE | Business | eq_ref | PRIMARY | PRIMARY | 4 | yuldi.BusinessesCategory.business_id | 1 | Using index |
Run Code Online (Sandbox Code Playgroud)
需要返工的三个方面
请看查询
SELECT COUNT(*) AS `count`
FROM `yuldi`.`businesses` AS `Business`
LEFT JOIN `yuldi`.`businesses_categories` AS `BusinessesCategory`
ON (`Business`.`id` = `BusinessesCategory`.`business_id`)
LEFT JOIN `yuldi`.`categories` AS `Category`
ON (`BusinessesCategory`.`category_id` = `Category`.`id`)
WHERE `Category`.`slug` = 'building-construction';
Run Code Online (Sandbox Code Playgroud)
您正在执行 LEFT JOIN。这不是进行 COUNT 所必需的。为什么 ?
如果是统计商家数量,只需要从一张表开始数
SELECT COUNT(*) AS `count`
FROM `yuldi`.`businesses` AS `Business`;
Run Code Online (Sandbox Code Playgroud)
由于您在 上有 WHERE 子句Category.slug
,因此需要 JOIN。您应该从 LEFT JOIN 切换到 INNER JOIN。这将产生一个较小的内部临时表。将在临时表中搜索 slug 'building-construction'。
从 EXPLAIN 计划中,我看到两个名称相似的索引
您需要查看它们的列并确保列列表不同。
您可能想要制作两个索引
ALTER TABLE BusinessesCategory
ADD INDEX bus_cat_ndx (business_id,category_id),
ADD INDEX cat_bus_ndx (category_id,business_id)
;
Run Code Online (Sandbox Code Playgroud)
拥有复合索引可能意味着更少地通过表来筛选 JOIN 信息。
请记住,这个建议是盲目的,因为我不知道您数据的关键分布。
收集索引统计信息是为了查询评估不会立即转化为慢查询。这种缓慢表现在真正的罪魁祸首:缓存。您的查询第二次运行得更快的原因与您第一次读取的数据有关。当您发出查询时,您需要的数据很可能在 MySQL 的缓存中不可用。
MySQL 的两个主要缓存是 InnoDB 缓冲池(用于访问 InnoDB 表的查询)和 MyISAM 键缓存(用于访问 MyISAM 表的查询)。
InnoDB 缓存数据和索引页,而 MyISAM 只缓存索引页。
当检索数据进行比较时,mysqld 会首先尝试确定它需要的数据是否在 RAM 中。有服务器状态变量可以监控:
如果您的查询第一次很慢,这仅意味着您查询所需的数据不在缓存中。这将是由你的任何指示Innodb_buffer_pool_reads或Key_reads递增。
第二次,同一查询的数据和/或索引页将在 RAM 中,并且更多地可用于您的查询和来自其他人的查询。
我建议您查看 InnoDB Buffer Pool 和/或 MyISAM key cache 的大小。
归档时间: |
|
查看次数: |
11075 次 |
最近记录: |