SQL 服务器是否优化了需要读取的数据?
Does SQL server optimize what data needs to be read?
我已经使用 BigQuery / Spark 几年了,但我对 SQL 服务器不是很熟悉。
如果我有这样的查询
with x AS (
SELECT * FROM bigTable1
),
y AS (SELECT * FROM bigTable2)
SELECT COUNT(1) FROM x
服务器 SQL 是否足够“聪明”以忽略无意义的数据获取?
注意:由于我的环境配置,我无法访问查询规划器进行故障排除。
与大多数领先的专业 DBMS 一样,SQL 服务器有一个统计优化器,确实可以消除从未使用过且不会影响结果的数据源。
但是请注意,这不适用于某些类型的错误,因此如果您的 bigTable1
或 bigTable2
不存在(或者您无法访问它们),查询将抛出编译错误,即使它永远不会真正使用这些表。
SQL 服务器拥有所有专业 RDBMS(IBM DB2、Oracle...)中最先进的优化器。
在优化algebriser之前将query转换,那只是一个“需求”(不是一个执行代码)变成一个已知的具有“代数树”的数学公式。这个数学对象是支持 Relational DBMS(由 Franck Edgar Codd 在 70 年代初开发的数学理论)的关系代数公式。
优化的第一步是通过简化数学公式完成的,就像你用多项式表达式所做的一样包括 x 和 y(例如:2x - 3y = 3x² - 5x + 7 <=> y = (3x² - 3x + 7 ) / 3)。
查询示例(来自 Chris Date “A Cure for Madness”):
随着 table :
CREATE TABLE T_MAD (TYP CHAR(4), VAL VARCHAR(16));
INSERT INTO T_MAD VALUES
('ALFA', 'ted'),('ALFA', 'chris'),('ALFA', 'michael'),
('NUM', '123'),('NUM', '4567'),('NUM', '89');
此查询将失败:
SELECT * FROM T_MAD
WHERE VAL > 1000;
因为 VAL 是字符串数据类型,在 WHERE 中进行比较时与数字值不兼容。
但是我们的 table 将 ALFA 值与 NUM 值区分开来。通过像这样使用 TYP 列对值添加限制:
SELECT * FROM T_MAD
WHERE TYP = 'NUM' AND VAL > 1000;
我的查询给出了正确的结果...
但所有这些查询也是如此:
SELECT * FROM T_MAD
WHERE VAL > 1000 AND TYP = 'NUM';
SELECT * FROM
(
SELECT * FROM T_MAD WHERE TYP = 'NUM'
) AS T
WHERE VAL > 1000;
SELECT * FROM
(
SELECT * FROM T_MAD WHERE VAL > 1000
) AS T
WHERE TYP = 'NUM';
最后一个很重要,因为子查询是第一个失败的...
那么这个突然不失败的子查询发生了什么?
事实上,algebriser 将所有这些查询重写为更简单的形式,该形式执行类似(不是说完全相同)的公式...
看看查询执行计划,它似乎严格等于!
注意 像 MySQL、MariaDB 或 PostGreSQL 这样的非专业 DBMS 将在最后一个失败.... open/free 无法模仿的大量 IT 开发人员和研究人员!
其次,优化器具有启发式规则,主要应用于语义级别。当查询文本中出现一些矛盾的情况时,执行计划被简化...
看看这两个查询:
SELECT * FROM T_MAD WHERE 1 = 2;
SELECT * FROM T_MAD WHERE 1 = 1;
第一个将不返回任何行,而第二个将返回 table 的所有行...优化器做了什么?查询执行计划给出答案:
查询执行计划中的术语“Analyse de constante”意味着优化器将无法访问 table...这将类似于您对上一个子查询的访问.. .
注意每个约束(PK, FK, UNIQUE, CHECK)都可以帮助优化器简化查询执行计划来优化性能!
第三,优化器将使用根据数据分布计算的直方图统计信息来预测在查询执行计划的每个步骤中将处理多少行...
关于 SQL 服务器查询优化器还有很多话要说,比如它与所有其他优化器反向工作的 fct,并且利用这种技术它可以预测自 18 年来所有丢失的索引其他 RDBMS 不能 !
PS:抱歉使用法语版的 SSMS...我在法国工作,帮助专业人士优化那里的数据库!
我已经使用 BigQuery / Spark 几年了,但我对 SQL 服务器不是很熟悉。
如果我有这样的查询
with x AS (
SELECT * FROM bigTable1
),
y AS (SELECT * FROM bigTable2)
SELECT COUNT(1) FROM x
服务器 SQL 是否足够“聪明”以忽略无意义的数据获取?
注意:由于我的环境配置,我无法访问查询规划器进行故障排除。
与大多数领先的专业 DBMS 一样,SQL 服务器有一个统计优化器,确实可以消除从未使用过且不会影响结果的数据源。
但是请注意,这不适用于某些类型的错误,因此如果您的 bigTable1
或 bigTable2
不存在(或者您无法访问它们),查询将抛出编译错误,即使它永远不会真正使用这些表。
SQL 服务器拥有所有专业 RDBMS(IBM DB2、Oracle...)中最先进的优化器。
在优化algebriser之前将query转换,那只是一个“需求”(不是一个执行代码)变成一个已知的具有“代数树”的数学公式。这个数学对象是支持 Relational DBMS(由 Franck Edgar Codd 在 70 年代初开发的数学理论)的关系代数公式。
优化的第一步是通过简化数学公式完成的,就像你用多项式表达式所做的一样包括 x 和 y(例如:2x - 3y = 3x² - 5x + 7 <=> y = (3x² - 3x + 7 ) / 3)。
查询示例(来自 Chris Date “A Cure for Madness”):
随着 table :
CREATE TABLE T_MAD (TYP CHAR(4), VAL VARCHAR(16));
INSERT INTO T_MAD VALUES
('ALFA', 'ted'),('ALFA', 'chris'),('ALFA', 'michael'),
('NUM', '123'),('NUM', '4567'),('NUM', '89');
此查询将失败:
SELECT * FROM T_MAD
WHERE VAL > 1000;
因为 VAL 是字符串数据类型,在 WHERE 中进行比较时与数字值不兼容。
但是我们的 table 将 ALFA 值与 NUM 值区分开来。通过像这样使用 TYP 列对值添加限制:
SELECT * FROM T_MAD
WHERE TYP = 'NUM' AND VAL > 1000;
我的查询给出了正确的结果...
但所有这些查询也是如此:
SELECT * FROM T_MAD
WHERE VAL > 1000 AND TYP = 'NUM';
SELECT * FROM
(
SELECT * FROM T_MAD WHERE TYP = 'NUM'
) AS T
WHERE VAL > 1000;
SELECT * FROM
(
SELECT * FROM T_MAD WHERE VAL > 1000
) AS T
WHERE TYP = 'NUM';
最后一个很重要,因为子查询是第一个失败的...
那么这个突然不失败的子查询发生了什么?
事实上,algebriser 将所有这些查询重写为更简单的形式,该形式执行类似(不是说完全相同)的公式...
看看查询执行计划,它似乎严格等于!
注意 像 MySQL、MariaDB 或 PostGreSQL 这样的非专业 DBMS 将在最后一个失败.... open/free 无法模仿的大量 IT 开发人员和研究人员!
其次,优化器具有启发式规则,主要应用于语义级别。当查询文本中出现一些矛盾的情况时,执行计划被简化...
看看这两个查询:
SELECT * FROM T_MAD WHERE 1 = 2;
SELECT * FROM T_MAD WHERE 1 = 1;
第一个将不返回任何行,而第二个将返回 table 的所有行...优化器做了什么?查询执行计划给出答案:
查询执行计划中的术语“Analyse de constante”意味着优化器将无法访问 table...这将类似于您对上一个子查询的访问.. .
注意每个约束(PK, FK, UNIQUE, CHECK)都可以帮助优化器简化查询执行计划来优化性能!
第三,优化器将使用根据数据分布计算的直方图统计信息来预测在查询执行计划的每个步骤中将处理多少行...
关于 SQL 服务器查询优化器还有很多话要说,比如它与所有其他优化器反向工作的 fct,并且利用这种技术它可以预测自 18 年来所有丢失的索引其他 RDBMS 不能 !
PS:抱歉使用法语版的 SSMS...我在法国工作,帮助专业人士优化那里的数据库!