【发布时间】:2010-11-08 22:04:19
【问题描述】:
这还没有解决,但我发现了原因:MySQL View containing UNION does not optimize well...In other words SLOW!
原帖:
我正在为游戏使用数据库。有两个相同的表equipment 和safety_dep_box。要检查玩家是否拥有一件装备,我想检查两张表。
我不想做两个查询,而是想利用 MySQL 中的 UNION 功能。我最近了解到我可以创建一个视图。这是我的看法:
CREATE VIEW vAllEquip AS SELECT * FROM equipment UNION SELECT * FROM safety_dep_box;
视图创建得很好。但是当我运行时
SELECT * FROM vAllEquip WHERE owner=<id>
查询需要很长时间,而独立的选择查询很快。我想我知道为什么,但我不知道如何解决它。
谢谢!
附:附加信息:
这两个表在结构上是相同的,但是因为它们是多 1 亿行表而被拆分。 该结构包括 int id 上的主键,int owner 上的多个索引。 我不明白的是以下之间的速度差异:
SELECT COUNT(*) FROM (SELECT * FROM equipment WHERE owner=1 UNION ALL SELECT * FROM safety_dep_box WHERE owner=1) AS uES;
0.42 秒
SELECT COUNT(*) FROM (SELECT * FROM equipment WHERE owner=1 UNION SELECT * FROM safety_dep_box WHERE owner=1) AS uES;
0.37 秒
SELECT COUNT(*) FROM vAllEquip WHERE owner=1;
60 秒后中止
版本:5.1.51
mysql> explain SELECT * FROM equipment UNION SELECT * FROM safety_dep_box;
+----+--------------+----------------+------+---------------+------+---------+------+---------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------+----------------+------+---------------+------+---------+------+---------+-------+
| 1 | PRIMARY | equipment | ALL | NULL | NULL | NULL | NULL | 1499148 | |
| 2 | UNION | safety_dep_box | ALL | NULL | NULL | NULL | NULL | 867321 | |
| NULL | UNION RESULT | <union1,2> | ALL | NULL | NULL | NULL | NULL | NULL | |
+----+--------------+----------------+------+---------------+------+---------+------+---------+-------+
带有 WHERE 子句
mysql> explain SELECT * FROM equipment WHERE owner=1 UNION ALL SELECT * FROM safety_dep_box WHERE owner=1
-> ;
+----+--------------+----------------+------+-----------------------+-------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------+----------------+------+-----------------------+-------+---------+-------+------+-------+
| 1 | PRIMARY | equipment | ref | owner,owner_2,owner_3 | owner | 4 | const | 1 | |
| 2 | UNION | safety_dep_box | ref | owner,owner_3 | owner | 4 | const | 1 | |
| NULL | UNION RESULT | <union1,2> | ALL | NULL | NULL | NULL | NULL | NULL | |
+----+--------------+----------------+------+-----------------------+-------+---------+-------+------+-------+
【问题讨论】:
-
您使用的是哪个版本的 MySQL?你能解释一下 SELECT * FROM 设备 UNION SELECT * FROM safety_dep_box; ?
-
我已经在我原来的帖子中解决了你的 2 个问题。
-
您需要解释with WHERE 子句。否则执行计划非常明显(从一个表中获取所有行,然后从另一个表中获取)。使用 WHERE 子句,EXPLAIN 将(可能)告诉您它从第一个表中获取少量行,然后在第二个表上进行某种表扫描(可能是因为缺少 UNION ALL,如下所述)。跨度>
-
我在 WHERE 中添加了 EXPLAIN。这是问题的核心——当我将 WHERE 子句添加到视图中的选择时——它不会传播到内部 SELECT 语句。据我所知,除了不使用视图之外,没有其他解决方案。