哪个更快:使用GROUP BY或子查询加入?

d4n*_*4nt 10 sql-server join group-by subquery sql-server-2008

假设我们有两个表:'Car'和'Part',在'Car_Part'中有一个连接表.说我想看到所有车辆中都有123部分.我能做到这一点:

SELECT Car.Col1, Car.Col2, Car.Col3 
FROM Car
INNER JOIN Car_Part ON Car_Part.Car_Id = Car.Car_Id
WHERE Car_Part.Part_Id = @part_to_look_for
GROUP BY Car.Col1, Car.Col2, Car.Col3
Run Code Online (Sandbox Code Playgroud)

或者我可以做到这一点

SELECT Car.Col1, Car.Col2, Car.Col3 
FROM Car
WHERE Car.Car_Id IN (SELECT Car_Id FROM Car_Part WHERE Part_Id = @part_to_look_for)
Run Code Online (Sandbox Code Playgroud)

现在,我内心的一切都想要使用第一种方法,因为我是由善良的父母抚养长大的,他们向我灌输了对次级查询和对集合理论的热爱的清教徒仇恨,但有人建议我做那么大GROUP BY比子查询更糟糕.

我应该指出我们在SQL Server 2008上.我还应该说实际上我想根据Part Id,Part Type以及其他可能的东西进行选择.所以,我想要做的查询实际上是这样的:

SELECT Car.Col1, Car.Col2, Car.Col3 
FROM Car
INNER JOIN Car_Part ON Car_Part.Car_Id = Car.Car_Id
INNER JOIN Part ON Part.Part_Id = Car_Part.Part_Id
WHERE (@part_Id IS NULL OR Car_Part.Part_Id = @part_Id)
AND (@part_type IS NULL OR Part.Part_Type = @part_type)
GROUP BY Car.Col1, Car.Col2, Car.Col3
Run Code Online (Sandbox Code Playgroud)

要么...

SELECT Car.Col1, Car.Col2, Car.Col3 
FROM Car
WHERE (@part_Id IS NULL OR Car.Car_Id IN (
    SELECT Car_Id 
    FROM Car_Part 
    WHERE Part_Id = @part_Id))
AND (@part_type IS NULL OR Car.Car_Id IN (
    SELECT Car_Id
    FROM Car_Part
    INNER JOIN Part ON Part.Part_Id = Car_Part.Part_Id
    WHERE Part.Part_Type = @part_type))
Run Code Online (Sandbox Code Playgroud)

Sir*_*bin 3

我有类似的数据,因此我检查了两种查询风格的执行计划。令我惊讶的是,子查询中的列 (CIS) 生成的执行计划的 I/O 成本比内连接 (IJ) 查询少 25%。在 CIS 执行计划中,我对中间表 (Car_Part) 进行了 2 次索引扫描,而对中间表进行了 2 次索引扫描,并在 IJ 中进行了相对更昂贵的哈希连接。我的索引很健康,但不是聚集的,因此按理说,通过聚集它们,索引扫描可能会更快一些。我怀疑这会影响哈希连接的成本,这是 IJ 查询中更昂贵的步骤。

就像其他人指出的那样,这取决于您的数据。如果您在这 3 个表中使用许多 GB 的数据,那么请放弃。 如果您的行数有数百或数千,那么您可能会因为很小的性能提升而感到烦恼。 我想说,IJ 查询的可读性要高得多,所以只要它足够好,请为任何接触您的代码的未来开发人员提供帮助,并为他们提供更易于阅读的内容。我的表中的行数为 188877、283912、13054,并且两个查询的返回时间比喝咖啡所需的时间还要短。

小后记:由于您没有聚合任何数值,因此看起来您的意思是选择不同的。除非您实际上要对组执行某些操作,否则最后使用 select unique 而不是 group by 更容易看到您的意图。IO 成本是相同的,但恕我直言,它更能表明你的意图。