SELECT * FROM表VS SELECT * FROM(SELECT * FROM表AS A)AS B的性能损失是什么
我的问题是:首先,SELECT *是否涉及对表中行的迭代,或者它是否只是将所有行作为块返回而没有任何迭代(因为没有给出WHERE子句),如果是这样,嵌套查询在示例中两个涉及迭代表两次,并将占用第一个查询的2倍?谢谢…
解决方法:
这个问题的答案取决于你是否在5.7之前或5.7之后使用mysql.我可能会略微改变你的问题,但希望以下内容能够捕捉到你所追求的内容.
SELECT * FROM Table通过聚簇索引(物理排序)进行表扫描.在没有主键的情况下,引擎可以使用一个主键.你说的没有where子句.不尝试过滤或选择其他索引.
Explain输出(见also)在摘要中显示1行.这是相对直接的.派生表B的解释输出和性能将根据您是否使用5.7之前的版本或5.7之后的版本而有所不同.
文档Derived Tables in MySQL 5.7很好地描述了版本5.6和5.7,其中后者将由于物化的派生表输出的变化被合并到外部查询中而不提供惩罚.在以前的版本中,使用派生的临时表忍受了大量的开销.
在5.7之前测试性能损失是非常容易的.所需要的只是一个中等大小的表,以查看您的问题派生表对影响性能的显着影响.以下示例位于5.6版的小表中:
explain
select qm1.title
from questions_mysql qm1
join questions_mysql qm2
on qm2.qid<qm1.qid
where qm1.qid>3333 and qm1.status='O';
+----+-------------+-------+-------+-----------------+---------+---------+------+-------+------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+-----------------+---------+---------+------+-------+------------------------------------------------+
| 1 | SIMPLE | qm1 | range | PRIMARY,cactus1 | PRIMARY | 4 | NULL | 5441 | Using where |
| 1 | SIMPLE | qm2 | ALL | PRIMARY,cactus1 | NULL | NULL | NULL | 10882 | Range checked for each record (index map: 0x3) |
+----+-------------+-------+-------+-----------------+---------+---------+------+-------+------------------------------------------------+
explain
select b.title from
( select qid,title from questions_mysql where qid>3333 and status='O'
) b
join questions_mysql qm2
on qm2.qid<b.qid;
+----+-------------+-----------------+-------+-----------------+---------+---------+------+-------+----------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------------+-------+-----------------+---------+---------+------+-------+----------------------------------------------------+
| 1 | PRIMARY | qm2 | index | PRIMARY,cactus1 | cactus1 | 10 | NULL | 10882 | Using index |
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 5441 | Using where; Using join buffer (Block Nested Loop) |
| 2 | DERIVED | questions_mysql | range | PRIMARY,cactus1 | PRIMARY | 4 | NULL | 5441 | Using where |
+----+-------------+-----------------+-------+-----------------+---------+---------+------+-------+----------------------------------------------------+
请注意,我确实更改了问题,但它说明了派生表的影响以及它们在5.7之前的版本中与优化程序一起使用的索引缺失.派生表在实现时会从索引中受益.但此后它作为临时表持续开销,并且在没有索引使用的情况下被合并到外部查询中. 5.7版本不是这种情况