MySQL视图花费太多时间来选择数据

Posted

技术标签:

【中文标题】MySQL视图花费太多时间来选择数据【英文标题】:MySQL view taking too much time to select data 【发布时间】:2013-01-21 10:31:27 【问题描述】:

在我正在处理的网页中,我需要根据三个表格中的不同用户详细信息显示一些统计信息。所以我有以下查询,我加入了更多不同的表:

SELECT *
FROM `user` `u`
LEFT JOIN `subscriptions` `s` ON `u`.`user_id` = `s`.`user_id`
LEFT JOIN `devices` `ud` ON `u`.`user_id` = `ud`.`user_id`
GROUP BY `u`.`user_id`

当我使用 LIMIT 1000 执行查询时,大约需要 0.05 秒,因为我在很多查询中使用了所有三个表中的数据,所以我决定把它放在里面VIEW:

CREATE VIEW `user_details` AS ( the same query from above )

现在当我跑步时:

SELECT * FROM user_details LIMIT 1000

大约需要 7-10 秒。

所以我的问题是我可以做些什么来优化视图,因为查询似乎很快,或者我应该整个查询而不是视图?

编辑:这是EXPLAIN SELECT * FROM user_details 返回的内容

+----+-------------+------------+--------+----------------+----------------+---------+------------------------+--------+-------+
| id | select_type | table      | type   | possible_keys  | key            | key_len | ref                    | rows   | Extra |
+----+-------------+------------+--------+----------------+----------------+---------+------------------------+--------+-------+
|  1 | PRIMARY     | <derived2> | ALL    | NULL           | NULL           | NULL    | NULL                   | 322666 |       |
|  2 | DERIVED     | u          | index  | NULL           | PRIMARY        | 4       | NULL                   | 372587 |       |
|  2 | DERIVED     | s          | eq_ref | PRIMARY        | PRIMARY        | 4       | db_users.u.user_id     |      1 |       |
|  2 | DERIVED     | ud         | ref    | device_id_name | device_id_name | 4       | db_users.u.user_id     |      1 |       |
+----+-------------+------------+--------+----------------+----------------+---------+------------------------+--------+-------+

4 行(8.67 秒)

这是explain 为查询返回的内容:

+----+-------------+-------+--------+----------------+----------------+---------+------------------------+--------+-------+
| id | select_type | table | type   | possible_keys  | key            | key_len | ref                    | rows   | Extra |
+----+-------------+-------+--------+----------------+----------------+---------+------------------------+--------+-------+
|  1 | SIMPLE      | u     | index  | NULL           | PRIMARY        | 4       | NULL                   | 372587 |       |
|  1 | SIMPLE      | s     | eq_ref | PRIMARY        | PRIMARY        | 4       | db_users.u.user_id     |      1 |       |
|  1 | SIMPLE      | ud    | ref    | device_id_name | device_id_name | 4       | db_users.u.user_id     |      1 |       |
+----+-------------+-------+--------+----------------+----------------+---------+------------------------+--------+-------+

3 行(0.00 秒)

【问题讨论】:

使用EXPLAIN 了解幕后情况。 从 EXPLAIN 看来,您正在加倍查询(select * from (select * from...))此外,您可能希望将限制放在视图中。只是我的 2 美分。 @JvO 是的,我将查询加倍,但视图不应该是这样工作的吗?并且视图内部的限制不是一个选项 你说得对,它应该可以工作;我唯一注意到的是EXPLAIN 为视图检查的行略有不同,322666 与 372587 用于“常规”查询。对我来说,这表明 mysql 优化器对您的查询中的某些内容感到困惑。如果我不得不猜测,那就是 GROUP BY。对查询/视图执行 COUNT() 并查看哪一个与这两个数字匹配。除此之外,恐怕这超出了我的范围...... mysql view performance的可能重复 【参考方案1】:

在性能方面,视图和连接非常糟糕。这或多或少适用于所有关系数据库管理系统。听起来很奇怪,因为这些系统就是为此而设计的,但它确实如此。

如果这是您页面上大量使用的查询,请尽量避免连接:而是创建一个由三个表填充的真实表(而不是视图)。您可以使用触发器自动化该过程。因此,每次将条目插入其中一个原始表时,触发器都会负责将数据传播到物理 user_details 表。

这种策略当然意味着对设置进行一次性投资,但您肯定会获得很多更好的性能。

【讨论】:

以上是关于MySQL视图花费太多时间来选择数据的主要内容,如果未能解决你的问题,请参考以下文章

mysql 简单更新 4000 万和 128GB RAM 花费太多时间

Android:Firebase 花费太多时间来获取数据

UIScrollView 花费太多时间

嵌套的 Foreach 循环花费了太多时间

保存到数据库需要花费太多时间

从服务器检索数据花费了太多时间