在大多数情况下,这两个SQL语句中的哪一个会花费更少的时间? 1)
SELECT table_a.foo,
table_b.zoo
FROM table_a,
table_b
WHERE table_a.id = table_b.id
AND table_b.bar = 'something'
2)
SELECT table_a.foo,
tableb.zoo
FROM table_a,
(SELECT *
FROM table_b
WHERE bar = 'something') AS tableb
WHERE table_a.id = tableb.id
或者他们是一样的吗? 似乎(2)会更快......
答案 0 :(得分:5)
其他答案和评论是猜测或概括。
真正的答案是它取决于几个方面,包括:
SQL优化器的实现;您使用的是哪个品牌的RDBMS? MySQL的? Microsoft SQL Server?甲骨文?您应该用适当的品牌标记您的问题。
表定义,包括相关索引。
表格的大小,以及与条件匹配的表格子集的大小。
相对于缓存大小的数据大小。
等
确实,SQL 假设是一个抽象的声明性语言,如@Colin'tHart在评论中提到的那样。因此,您应该能够声明两个不同的查询,这些查询将产生相同的结果,并且RDBMS应该将其转换为收集该数据的最佳方式。理论上很好,但实际上,魔术只与软件设计人员实现代码的案例数一样好。
所以你在这个问题的标题中提到的非常基本的通用sql(效率)主体应该是:
衡量效果 - 不要猜测或概括。
要尝试进一步调查此问题,您应该从SQL优化器获取有关如何访问表和索引以实现查询的报告。大多数RDBMS产品都有一些名为 EXPLAIN 的语句变体,允许您为给定查询获取此报告。如果RDBMS成功地将此案例抽象化,那么对于您显示的两个示例查询,EXPLAIN报告应该相同。
例如,我尝试对测试MySQL数据库进行类似的查询。 EXPLAIN显示运行派生表子查询还有一个额外的步骤,然后用于查找匹配的行。
mysql> EXPLAIN SELECT c.*, t.* FROM cast_info c
JOIN ( SELECT * FROM title WHERE title = 'Star Wars') t ON c.movie_id = t.id\G
*************************** 1. row ***************************
id: 1
select_type: PRIMARY
table: <derived2>
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 8
Extra: NULL
*************************** 2. row ***************************
id: 1
select_type: PRIMARY
table: c
type: ref
possible_keys: movie_id
key: movie_id
key_len: 4
ref: t.id
rows: 9
Extra: NULL
*************************** 3. row ***************************
id: 2
select_type: DERIVED
table: title
type: ref
possible_keys: title
key: title
key_len: 152
ref: const
rows: 8
Extra: Using where
在没有子查询的情况下进行普通连接有点不同,它仍然首先搜索同一个表,但它不必将其视为派生表。
mysql> EXPLAIN SELECT c.*, t.* FROM cast_info c
JOIN title t ON c.movie_id = t.id WHERE title = 'Star Wars'\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t
type: ref
possible_keys: PRIMARY,title
key: title
key_len: 152
ref: const
rows: 8
Extra: Using where
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: c
type: ref
possible_keys: movie_id
key: movie_id
key_len: 4
ref: imdb.t.id
rows: 9
Extra: NULL
使用SQL-89(逗号样式)连接语法与使用JOIN
语法的查询完全相同:
mysql> EXPLAIN SELECT c.*, t.* FROM cast_info c, title t
WHERE c.movie_id = t.id AND title = 'Star Wars'\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t
type: ref
possible_keys: PRIMARY,title
key: title
key_len: 152
ref: const
rows: 8
Extra: Using where
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: c
type: ref
possible_keys: movie_id
key: movie_id
key_len: 4
ref: imdb.t.id
rows: 9
Extra: NULL
这只是MySQL的结果。另一个RDBMS的优化器可能表现不同,它的EXPLAIN输出肯定会有所不同。关键是您可以使用工具为自己测试查询的优化计划。
EXPLAIN报告是一个这样的工具。但EXPLAIN通常只显示优化器计划执行的操作,而不实际运行查询。您还可以使用 profiler 工具运行查询,并获得更精确的执行时间度量。可用的Profiler工具取决于您的RDBMS品牌。
答案 1 :(得分:0)
两者都不如此查询有效:
SELECT
table_a.foo,
table_b.zoo
FROM table_a
JOIN table_b
ON table_a.id = table_b.id
AND table_b.bar = 'something'
注意tableb上的额外条件是如何处于连接条件中,不是 where子句,这意味着它是在进行连接时进行评估,这可以避免添加临时结果集的大量行数。
如果它在where子句中,则在完成所有连接后将对其进行评估,因为where子句是结果集上的过滤器。
答案 2 :(得分:-1)
根据我的理解,查询1将花费更少的时间,因为在第二个查询中
SELECT *
FROM table_b
WHERE bar = 'something'
将首先运行,然后将与外部查询进行交叉检查。