GROUP BY 语句什么会更快
What will be faster for GROUP BY statement
假设我有接下来的两个 SQL 服务器表:
CREATE TABLE Users (
id INT IDENTITY(1, 1) PRIMARY KEY,
name VARCHAR(100) NOT NULL
)
CREATE TABLE UserLogins (
id INT IDENTITY(1, 1) PRIMARY KEY,
user_id INT REFERENCES Users(id) NOT NULL,
login VARCHAR(100) NOT NULL
)
而且我需要计算每个用户的用户登录次数。并且查询结果应该包含用户名,例如。
哪个查询会更快:
SELECT MAX(name), count(*)
FROM Users u
INNER JOIN UserLogins ul ON ul.user_id = u.id
GROUP BY u.id
或下一个:
SELECT name, count(*)
FROM Users u
INNER JOIN UserLogins ul ON ul.user_id = u.id
GROUP BY u.name
因此,我不确定是否最好按具有索引的列进行分组,然后使用 MAX
或 MIN
聚合函数。或者只是按 Users.name
分组,它没有任何索引。
提前致谢!
答案是:两者都不正确。
第二个版本完全错误,因为 name
不是唯一的。第一个版本是正确的,虽然它可能效率不高。
由于 name
对 id
具有 功能依赖性 ,因此 id
的每个唯一值也定义了 [=11= 的值].按 name
分组是错误的,因为 name
不一定是唯一的。仅按 id
分组意味着您需要聚合 name
,如果存在函数依赖性,这将毫无意义。所以你实际上想按 both 列分组:
SELECT
u.name,
count(*)
FROM Users u
INNER JOIN UserLogins ul ON ul.user_id = u.id
GROUP BY
u.id,
u.name;
请注意,id
实际上不需要选择。
此查询几乎肯定会比单独按 name
分组更快,因为服务器无法推断 name
是唯一的,需要对其进行排序和聚合。
它也可能比按 id
分组更快,尽管这可能取决于优化器是否足够聪明来推断函数依赖性(因此不需要聚合)。即使它不聪明,这也可能不会很慢,因为 id
已经是唯一的,所以扫描 id
上的索引不需要排序,只需要聚合。
假设我有接下来的两个 SQL 服务器表:
CREATE TABLE Users (
id INT IDENTITY(1, 1) PRIMARY KEY,
name VARCHAR(100) NOT NULL
)
CREATE TABLE UserLogins (
id INT IDENTITY(1, 1) PRIMARY KEY,
user_id INT REFERENCES Users(id) NOT NULL,
login VARCHAR(100) NOT NULL
)
而且我需要计算每个用户的用户登录次数。并且查询结果应该包含用户名,例如。 哪个查询会更快:
SELECT MAX(name), count(*)
FROM Users u
INNER JOIN UserLogins ul ON ul.user_id = u.id
GROUP BY u.id
或下一个:
SELECT name, count(*)
FROM Users u
INNER JOIN UserLogins ul ON ul.user_id = u.id
GROUP BY u.name
因此,我不确定是否最好按具有索引的列进行分组,然后使用 MAX
或 MIN
聚合函数。或者只是按 Users.name
分组,它没有任何索引。
提前致谢!
答案是:两者都不正确。
第二个版本完全错误,因为 name
不是唯一的。第一个版本是正确的,虽然它可能效率不高。
由于 name
对 id
具有 功能依赖性 ,因此 id
的每个唯一值也定义了 [=11= 的值].按 name
分组是错误的,因为 name
不一定是唯一的。仅按 id
分组意味着您需要聚合 name
,如果存在函数依赖性,这将毫无意义。所以你实际上想按 both 列分组:
SELECT
u.name,
count(*)
FROM Users u
INNER JOIN UserLogins ul ON ul.user_id = u.id
GROUP BY
u.id,
u.name;
请注意,id
实际上不需要选择。
此查询几乎肯定会比单独按 name
分组更快,因为服务器无法推断 name
是唯一的,需要对其进行排序和聚合。
它也可能比按 id
分组更快,尽管这可能取决于优化器是否足够聪明来推断函数依赖性(因此不需要聚合)。即使它不聪明,这也可能不会很慢,因为 id
已经是唯一的,所以扫描 id
上的索引不需要排序,只需要聚合。