使用UNION在VIEW中级联WHERE子句

时间:2010-11-08 22:04:20

标签: mysql view union

这没有解决,但我找到了原因:MySQL View containing UNION does not optimize well...In other words SLOW!


原帖:

我正在使用数据库进行游戏。有两个相同的表equipmentsafety_dep_box。为了检查一名球员是否有一件装备,我想检查两张桌子。

我想利用MySQL中的UNION功能,而不是进行两次查询。我最近了解到我可以创建一个VIEW。这是我的观点:

CREATE VIEW vAllEquip AS SELECT * FROM equipment UNION SELECT * FROM safety_dep_box;

视图创建得很好。但是当我跑步时

SELECT * FROM vAllEquip WHERE owner=<id>

查询需要永远,而独立选择查询很快。我想我知道为什么,但我不知道如何解决它。

谢谢!

P.S。附加信息:

这两个表在结构上是相同的,但是因为它们是1亿到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 |       |
+----+--------------+----------------+------+-----------------------+-------+---------+-------+------+-------+

2 个答案:

答案 0 :(得分:2)

首先,你应该使用UNION ALL而不是普通的UNION。使用普通UNION,引擎将尝试对结果集进行重复数据删除。这可能是你问题的根源。

其次,你需要两个表中的所有者索引,而不仅仅是一个。理想情况下,它们将是整数列。

第三,Randolph是对的,你不应该在SELECT语句中使用“*”。列出您想要包含的所有列。这在UNION中尤其重要,因为列必须完全匹配,如果两个表中的列顺序存在分歧,则可能会强制进行某种类型转换,这会花费您一些时间。

最后,短语“有两个相同的表”几乎总是一个提示,你的数据库没有最佳设计。这些应该是一张桌子。要指示项目的所有权,您的safety_dep_box表应仅包含项目的ownerID和itemID(用于关联设备和播放器),还可能包含其他自动编号的整数键列。

答案 1 :(得分:0)

首先,不要在视图中使用SELECT *。这是懒惰的代码。其次,在不知道基表的样子的情况下,我们甚至不太可能帮助你。

它永远需要的原因是它必须构建完整的结果然后过滤它。您需要owner字段上的索引,无论它们是什么。