这里有两个等价的查询(因为外键约束+主键):
CREATE TABLE customers ( id int PRIMARY KEY );
CREATE TABLE orders ( id int, customer_id int );
ALTER TABLE orders ADD FOREIGN KEY (customer_id) REFERENCES customers(id);
SELECT id
, (SELECT 1 FROM customers c WHERE c.id = o.id) one
FROM orders o;
SELECT o.id
, 1 one
FROM orders o
JOIN customers c
ON c.id = o.customer_id;
在这两种情况下,
orders
的每一行都会在结果中有一行。
这也意味着,如果所有这些查询(其中一个)是其他查询的子查询,并且其他查询不使用
one
列,则可以跳过连接。
我的问题是:MySQL 是否足够聪明,可以在这两种情况下跳过连接?如果我切换到
NULL
列和 LEFT JOIN
会怎样?
我现在正在努力提出一些意见,以非规范化一些报告表。所以我需要了解是否有一些规范格式(bikeshedding?)我应该用于这样的事情以确保我的巨大视图根据需要得到有效和最少的处理。
它绝对能够从子查询、CTE 和 VIEW 中优化掉未使用的列和查找。
它具体做什么取决于版本和确切的 DDL、查询和索引统计信息。在 MariaDB 上
ANALYZE FORMAT=JSON SELECT ...
将向您展示实际的执行计划。在 Oracle MySQL 上,使用 EXPLAIN ANALYZE SELECT ...
.
要记住的是,查询计划会随着表的增长而变化(并且随着统计数据变得陈旧,偶尔执行一次 ANALYZE TABLE)。而且,现实世界的应用程序查询模式很难预测。
如果你的应用变得非常大,你可能想要禁用外键检查并用好的代码来强制完整性。强制 FK 占用 CPU 时间和 IO。因此,在其他条件相同的情况下,不要依赖 FK 之类的约束。编写您的代码,以便尽可能不需要它们。 (但是,当然,如果您的代码在启用 FK 约束的情况下更有意义,请继续以这种方式编写。)
设计您的查询、CTE、VIEW 以及所有这些,以便它们易于阅读和推理。让您的应用正常运行。然后,如果您有幸拥有一个不断增长的应用程序和不断增长的表,请每三个月左右重新访问一次瓶颈查询计划。
我设计了表、索引和约束,将它们投入生产,然后不得不向我的继任者解释它们。但是,在我交接工作时,我从来没有,甚至一次,“哇,我应该让这个数据库更复杂或更聪明”。很多时候我都在想“我希望我以前的自己设计得更简单一些”。
流传着一句口号:“过早优化是万恶之源”。太夸张了。但公平地说,过早的数据库优化