在我正在处理的网页中,我需要根据三个表中的不同用户详细信息显示一些统计信息。所以我有以下查询,我将其连接到更多不同的表:
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 秒)
如果涉及到性能,视图和联接是非常糟糕的。对于所有关系数据库管理系统来说,这或多或少都是正确的。听起来很奇怪,因为这就是这些系统的设计目的,但事实确实如此。
如果这是页面上大量使用的查询,请尽量避免联接:而是创建一个从三个表填充的实际表(而不是视图)。 您可以使用触发器自动执行该过程。因此,每次将条目插入到原始表之一时,触发器都会注意将数据传播到物理user_details
表。
这种策略当然意味着对设置的一次性投资,但您肯定会获得更好的性能。