Agi*_*Agi 2 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
Run Code Online (Sandbox Code Playgroud)
考虑到查询是由依赖对象处理的,但只是(正确?)允许一个 WHERE 条件。我认为至少不会有很多数据被提取到您最喜欢的语言中,但是如果这是一个足够的优化并且可能数据库仍然需要一些时间来完成查询,我会重新考虑。
或者最好去掉那个查询并编写一个单独的查询方法,它也有 where 和一个LIMIT 1子句?
在MySQL 中,没有。
外部查询中的谓词不会“下推”到内联视图查询中。
内联视图中的查询首先被处理,独立于外部查询。(MySQL 将优化该视图查询,就像如果您单独提交它会优化该查询一样。)
MySQL 处理此查询的方式:内联视图查询首先运行,结果具体化为“派生表”。也就是说,该查询的结果集在某些情况下作为临时表存储在内存中(如果它足够小,并且不包含 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 不会从内联视图中“优化”任何不需要的列。如果内联视图查询是 a SELECT *,则所有列都将在派生表中表示,无论这些列是否在外部查询中被引用。
这可能会导致一些重大的性能问题,尤其是当我们不了解 MySQL 如何处理语句时。(而且 MySQL 处理语句的方式与其他关系数据库,如 Oracle 和 SQL Server有很大不同。)
您可能听说过“避免在 MySQL 中使用视图”的建议。这个一般建议(适用于“存储”视图和“内联”视图)背后的原因是可能会不必要地引入重要的性能问题。
例如,对于此查询:
SELECT q.name
FROM ( SELECT h.*
FROM huge_table h
) q
WHERE q.id = 42
Run Code Online (Sandbox Code Playgroud)
MySQL 不会将谓词“推”id=42到视图定义中。MySQL 首先运行内联视图查询,并实质上创建huge_table, 作为未索引的 MyISAM 表的副本。完成后,外部查询将扫描表的副本,以定位满足谓词的行。
如果我们改为重写查询以将谓词“推送”到视图定义中,如下所示:
SELECT q.name
FROM ( SELECT h.*
FROM huge_table h
WHERE h.id = 42
) q
Run Code Online (Sandbox Code Playgroud)
我们期望从视图查询返回一个小得多的结果集,并且派生表应该小得多。MySQL 还能够有效地利用索引ON huge_table (id)。但是仍然有一些与具体化派生表相关的开销。
如果我们从视图定义中消除不必要的列,效率会更高(特别是如果有很多列、任何大列或任何具有 MEMORY 引擎不支持的数据类型的列):
SELECT q.name
FROM ( SELECT h.name
FROM huge_table h
WHERE h.id = 42
) q
Run Code Online (Sandbox Code Playgroud)
完全消除内联视图会更有效:
SELECT q.name
FROM huge_table q
WHERE q.id
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
100 次 |
| 最近记录: |