下面是两个等价的查询(因为外键约束+主键):
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?)我应该用于这样的事情,以确保我的巨大视图能够有效地进行最低限度的处理。
1条答案
按热度按时间eimct9ow1#
它绝对能够优化子查询、CTE和VIEW中未使用的列和查找。
它具体做什么取决于版本和确切的DDL、查询和索引统计信息。在MariaDB上,
ANALYZE FORMAT=JSON SELECT ...
将显示实际的执行计划。在Oracle MySQL上,使用EXPLAIN ANALYZE SELECT ...
。需要记住的是,查询计划会随着表的增长而变化(随着统计数据变得陈旧,请偶尔执行ANALYZE TABLE)。
如果你的应用变得很大,你可能想禁用外键检查,并使用好的代码来强制完整性。强制的FK占用CPU时间和IO。所以,在其他条件相同的情况下,不要依赖像FK这样的约束。尽可能编写不需要它们的代码。(但是,当然,如果你的代码在启用FK约束时更有意义,那就继续这样写吧。)
设计您的查询、CTE、VIEW等,使其易于阅读和推理。让您的应用正常工作。然后,如果您有幸拥有一个不断增长的应用程序,其中的表不断增长,请每三个月左右重新审视瓶颈查询计划。
我设计了表、索引和约束,将它们投入生产,然后不得不向我的继任者解释它们。然而,我从来没有,甚至一次,在我移交工作时,“哇,我应该让这个数据库更复杂或更聪明”。很多时候我想“我希望以前的自己能设计得更简单”。
有一个口号说“过早的优化是万恶之源”。这是一个夸张的说法。但公平地说,过早的数据库优化