原帖:
我正在使用数据库进行游戏。有两个相同的表equipment
和safety_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 | |
+----+--------------+----------------+------+-----------------------+-------+---------+-------+------+-------+
答案 0 :(得分:2)
首先,你应该使用UNION ALL而不是普通的UNION。使用普通UNION,引擎将尝试对结果集进行重复数据删除。这可能是你问题的根源。
其次,你需要两个表中的所有者索引,而不仅仅是一个。理想情况下,它们将是整数列。
第三,Randolph是对的,你不应该在SELECT语句中使用“*”。列出您想要包含的所有列。这在UNION中尤其重要,因为列必须完全匹配,如果两个表中的列顺序存在分歧,则可能会强制进行某种类型转换,这会花费您一些时间。
最后,短语“有两个相同的表”几乎总是一个提示,你的数据库没有最佳设计。这些应该是一张桌子。要指示项目的所有权,您的safety_dep_box表应仅包含项目的ownerID和itemID(用于关联设备和播放器),还可能包含其他自动编号的整数键列。
答案 1 :(得分:0)
首先,不要在视图中使用SELECT *。这是懒惰的代码。其次,在不知道基表的样子的情况下,我们甚至不太可能帮助你。
它永远需要的原因是它必须构建完整的结果然后过滤它。您需要owner
字段上的索引,无论它们是什么。