我正在尝试在Oracle中运行以下SQL语句,并且运行很长一段时间:
SELECT orderID FROM tasks WHERE orderID NOT IN (SELECT DISTINCT orderID FROM tasks WHERE engineer1 IS NOT NULL AND engineer2 IS NOT NULL)
如果我只运行IN子句中的子部分,那么它将在Oracle中非常快速地运行,即
SELECT DISTINCT orderID FROM tasks WHERE engineer1 IS NOT NULL AND engineer2 IS NOT NULL
为什么在Oracle中整个语句要花这么长时间?在SQL Server中,整个语句运行很快。
另外,我应该使用更简单/不同/更好的SQL语句吗?
有关该问题的更多详细信息:
以防万一它有所不同,表中约有12万行,每个订单有3个任务,因此约有40k个不同的订单。
对答案的回应:
我猜想在原始SQL语句中,子查询每次都针对SQL语句第一部分中的每一行运行-即使它是静态的,应该只需要运行一次?
执行中
ANALYZE TABLE tasks COMPUTE STATISTICS;
使我原来的SQL语句执行得更快。
尽管我仍然很好奇为什么必须这样做,以及是否/何时需要再次运行它?
统计信息提供了Oracle基于成本的优化器信息,该信息是确定不同执行计划的效率所必需的:例如,表中的行数,行的平均宽度,每列的最高和最低值,每列的不同值的数量,索引的聚类因子等。 在小型数据库中,您可以设置一个工作来每晚收集统计信息,而不必理会它。实际上,这是10g以下的默认设置。对于较大的实现,通常必须权衡执行计划的稳定性和数据更改的方式,这是一个棘手的平衡。 Oracle还具有称为“动态采样”的功能,该功能用于对表进行采样以确定执行时的相关统计信息。它更常用于数据仓库,因为对于长时间运行的查询而言,其采样开销超过了潜在的性能提升。
统计信息提供了Oracle基于成本的优化器信息,该信息是确定不同执行计划的效率所必需的:例如,表中的行数,行的平均宽度,每列的最高和最低值,每列的不同值的数量,索引的聚类因子等。
在小型数据库中,您可以设置一个工作来每晚收集统计信息,而不必理会它。实际上,这是10g以下的默认设置。对于较大的实现,通常必须权衡执行计划的稳定性和数据更改的方式,这是一个棘手的平衡。
Oracle还具有称为“动态采样”的功能,该功能用于对表进行采样以确定执行时的相关统计信息。它更常用于数据仓库,因为对于长时间运行的查询而言,其采样开销超过了潜在的性能提升。
如果您分析所涉及的表,这种类型的问题通常会消失(因此,Oracle对数据的分布有了更好的了解)