关于查询优化,我想知道像下面这样的语句是否得到了优化:
select *
from (
select *
from table1 t1
join table2 t2 using (entity_id)
order by t2.sort_order, t1.name
) as foo -- main query of object
where foo.name = ?; -- inserted
考虑到查询由一个依赖对象处理,但只是(正确地?)允许一个人加入 WHERE 条件。我认为至少没有很多数据被提取到您最喜欢的语言中,但我正在重新考虑这是否是一个充分的优化,也许数据库仍然需要一些时间来完成查询。
或者是否更好地取出该查询并编写一个单独的查询方法,该方法具有 where 和可能还有一个 LIMIT 1
子句?
最佳答案
在 MySQL 中,没有。
外部查询中的谓词不会被“推”到内联 View 查询中。
首先处理内联 View 中的查询,独立于外部查询。 (如果您单独提交,MySQL 将优化该 View 查询,就像它优化该查询一样。)
MySQL 处理此查询的方式:首先运行内联 View 查询,结果具体化为“派生表”。也就是说,该查询的结果集在某些情况下作为临时表存储在内存中(如果它足够小,并且不包含 MEMORY 引擎不支持的任何列。否则,它会被分解为磁盘作为 MyISAM 表,使用 MyISAM 存储引擎。
一旦派生表被填充,外部查询就会运行。
(请注意,派生表没有有任何索引。在 5.6 之前的 MySQL 版本中确实如此;我认为 5.6 中有一些改进,MySQL 将实际创建索引。
澄清:派生表上的索引:从 MySQL 5.6.3 开始,“在查询执行期间,优化器可能会向派生表添加索引以加快从中检索行的速度。”引用:http://dev.mysql.com/doc/refman/5.6/en/subquery-optimization.html
此外,我认为 MySQL 不会从内联 View 中“优化掉”任何不需要的列。如果内联 View 查询是 SELECT *
,则所有列都将在派生表中表示,无论这些列是否在外部查询中被引用。
这可能会导致一些严重的性能问题,尤其是当我们不了解 MySQL 如何处理一条语句时。 (而且 MySQL 处理语句的方式与其他关系数据库(如 Oracle 和 SQL Server)显着不同。)
您可能听说过“避免在 MySQL 中使用 View ”的建议。此一般建议(适用于“存储” View 和“内联” View )背后的原因是可能会不必要地引入重大性能问题。
例如,对于这个查询:
SELECT q.name
FROM ( SELECT h.*
FROM huge_table h
) q
WHERE q.id = 42
MySQL 不会将谓词 id=42
向下“推送”到 View 定义中。 MySQL 首先运行内联 View 查询,并实质上创建了 huge_table
的副本,作为未索引的 MyISAM 表。完成后,外部查询将扫描表的副本,以定位满足谓词的行。
如果我们改写查询以将谓词“推送”到 View 定义中,如下所示:
SELECT q.name
FROM ( SELECT h.*
FROM huge_table h
WHERE h.id = 42
) q
我们期望 View 查询返回的结果集要小得多,派生表也应该小得多。 MySQL 也将能够有效地利用索引 ON huge_table (id)
。但是仍然存在一些与具体化派生表相关的开销。
如果我们从 View 定义中删除不必要的列,那会更有效(特别是如果有很多列,有任何大列,或者任何列的数据类型不受 MEMORY 引擎支持):
SELECT q.name
FROM ( SELECT h.name
FROM huge_table h
WHERE h.id = 42
) q
如果完全消除内联 View 会更有效:
SELECT q.name
FROM huge_table q
WHERE q.id
关于mysql - 来自子查询表的查询是否得到优化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26028480/