【发布时间】:2020-08-05 04:58:18
【问题描述】:
寻求关于我是否可以改进我的数据库语句或者我是否应该开始缓存查询结果以提高性能的建议。
架构设置为Many-To-Many Polymorphic 关系。我有一个包含视频信息的Videos 表、一个包含所有类别的Category 表和一个包含数据透视信息的Categorizable 表。
Videos 和 Categorizable 之间的比例约为 1:4。 (即每个视频至少有 4 个以上的类别)。
访问具有 40 行限制和 WITHOUT 偏移量的数据透视数据时的结果是:~1.2s+。 当偏移量 > 50,000 行时,添加偏移量会增加更多。
虽然 1.2 秒看起来很小,但这只是整个数据集的一小部分,最终包含大约 3000 万条视频记录(因此有大约 12+ 百万条可分类记录)。我担心每百万条记录会增加 1.2 秒。
数据库架构
视频表:
-------------------------------------------------- ---------------------- 编号 |标题 |作者 |意见 |持续时间 |等等。 -------------------------------------------------- ---------------------- 1 |最大的词是什么? |字典 | 3432 | 600 | ... 2 | 2020 年年度视频综述 |优酷 | 165 |第945章... 3 |谷歌搜索引擎优化帮助 |谷歌 | 1401 | 287 | ... ↓ 101234 |如何煮意大利面 |优酷 | 9401 | 87 | ...索引:
-------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------- 表 |非唯一 |键名 | Seq_in_index |列名 |整理 |基数|子部分 |包装 |空 |索引类型 |评论 |索引评论 |可见 |表达 -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------- 视频 | 0 |初级 | 1 |编号 |一个 | 253057 |空 |空 | | BTREE | | |是 |空值 视频 | 1 | idx_videos_views | 1 |意见 |一个 | 102188 |空 |空 |是 | BTREE | | |是 |空值分类表:
-------------------------------------------------- ------------ 编号 |类别 ID |可分类 ID |可分类类型 -------------------------------------------------- ------------ 1 | 5 | 1 | '视频' 2 | 100 | 2 | '视频' 3 | 31 | 3 | '视频' ↓ 299052 | 65 | 101234 | '视频'索引:
-------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ------------------------------------------------- 表 |非唯一 |键名 | Seq_in_index |列名 |整理 |基数|子部分 |包装 |空 |索引类型 |评论 |索引评论 |可见 |表达 -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ------------------------------------------------- 分类 | 0 |初级 | 1 |编号 |一个 | 296745 |空 |空 | | BTREE | | |是 |空值 分类 | 1 | idx_category_id | 1 |类别 ID |一个 | 82 |空 |空 | | BTREE | | |是 |空值 分类 | 1 | idx_categorizable_id | 1 |分类ID |一个 | 104705 |空 |空 | | BTREE | | |是 |空值类别表:
-------------------- 编号 |姓名 -------------------- 1 |教育 2 |健康 3 |娱乐 ↓ 100 |消息索引:
-------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ------------------------------------------------- 表 |非唯一 |键名 | Seq_in_index |列名 |整理 |基数|子部分 |包装 |空 |索引类型 |评论 |索引评论 |可见 |表达 -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ------------------------------------------------- 类别 | 0 |初级 | 1 |编号 |一个 | 100 |空 |空 | | BTREE | | |是 |空值MySQL
类型:InnoDB
Laravel 查询:
Category::where('id', $cat)
->with(['videos' => function($query){
return $query->take(40)->orderby('views');
}])
->get();
变成 MySQL 查询:
SELECT `videos`.`id`, `views`
FROM `videos` inner join `categorizables`
ON `videos`.`id` = `categorizables`.`categorizable_id`
WHERE `categorizables`.`category_id` = 1
ORDER BY `views` desc
LIMIT 40 offset 0
性能结果
以下是 MySQL 的性能输出
-------------------------------------------------- -------- 舞台 |期间 -------------------------------------------------- -------- 阶段/sql/开始 | 0.000068 stage/sql/Executing 交易钩子开始。 | 0.000000 阶段/sql/开始 | 0.000003 阶段/sql/检查权限 | 0.000001 阶段/sql/检查权限 | 0.000001 stage/sql/开表| 0.000038 阶段/sql/init | 0.000003 stage/sql/系统锁 | 0.000005 阶段/sql/优化 | 0.000007 阶段/sql/统计 | 0.005628 阶段/sql/准备 | 0.000008 stage/sql/创建 tmp 表 | 0.000033 阶段/sql/执行 | 1.273442 阶段/sql/结束 | 0.000001 阶段/sql/查询结束 | 0.000001 阶段/sql/等待处理程序提交 | 0.000008 阶段/sql/删除 tmp 表 | 0.000003 阶段/sql/关闭表| 0.000006 stage/sql/释放项目 | 0.000080 阶段/sql/清理| 0.000000具体来说:
stage/sql/executing | 1.273442
查询费用:
---------------------------------- 变量名 |价值 ---------------------------------- Last_query_cost | 107258.575124编辑:
解释查询
带排序:
-------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ----------------- 编号 |选择类型 |表|隔断 |类型 |可能的键 |关键 | key_len |参考 |行 |过滤 |额外的 -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ----------------- 1 |简单 |分类 |空 |参考 | idx_category_id,idx_categorizable_id | idx_category_id | 4 |常量 | 51210 | 100.00 |使用临时的;使用文件排序 1 |简单 |视频 |空 | eq_ref |初级 |初级 | 4 | dev_db.categorizables.categorizable_id | 1 | 100.00 |使用索引没有排序:
-------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ---------------------------------- 编号 |选择类型 |表|隔断 |类型 |可能的键 |关键 | key_len |参考 |行 |过滤 |额外的 -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ---------------------------------- 1 |简单 |视频 |空 |索引 |空 |初级 | 4 |空 | 40 | 100.00 |向后索引扫描;使用索引【问题讨论】:
-
所以,现在我们看到排序会减慢查询速度,我们可以将其分解为几个查询。 (现在尽量避免加入)。我看到的问题是 category_id 的索引基数是 82(对于你的大表来说太小了)
-
不幸的是,我不能忽略 INNER JOIN,因为它是应用程序的重要组成部分 - 能够通过类别对视频进行排序是必不可少的。我会将索引基数更新为更高的值,但这是通过 MySQL 工作台自动设置的(不确定是否正确)。我很难理解为什么在 300k 可分类行上需要这么长时间。
-
您无法更新它。一个黑客可以提供帮助。如果您知道您将获得的所有行的“视图”多于 N,您可以尝试将其添加到查询中
-
通过排序会影响 51210 行,目标是降低此值
-
views在哪个表中??它有很大的不同。请提供SHOW CREATE TABLE。
标签: mysql database laravel performance database-design