mysql - 来自子查询表的查询是否得到优化?

标签 mysql sql postgresql sql-execution-plan

关于查询优化,我想知道像下面这样的语句是否得到了优化:

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/

相关文章:

postgresql - 多对一 PostgreSQL 类(class)名称 : Unesco Heritage Sites Many-to-One

mysql - 为什么docker compose用错误的名称创建mysql容器?

mysql - 如何比较3个表并在mysql中合并它们的列

php - MySQL 查询 : generate a report of the top votes for the each food type

sql - 在窗口函数中计算运行总和

postgresql - 获取postgresql查询中每条记录的倒数第二行

mysql - PHP 和 MYSQL - 每天限制数据库中的用户?

sql - min 和 max 不适用于位字段是否有任何原因

c# - linq中tsql如何查询

mysql - HAVING 子句中的多个聚合函数