null 在性能调优中的作用
Role of null in performance tuning
此查询与查询的性能调整有关。
我有一个 table TEST1,它有 200,000 行。
table 结构如下。
ACCOUNT_NUMBER VARCHAR2(16)
BRANCH VARCHAR2(10)
ACCT_NAME VARCHAR2(100)
BALANCE NUMBER(20,5)
BANK_ID VARCHAR2(10)
SCHM_CODE VARCHAR2(10)
CUST_ID VARCHAR2(10)
指标如下
fields Index Name Uniquness
ACCOUNT_NUMBER IDX_TEST_ACCT UNIQUE
SCHM_CODE,BRANCH IDX_TEST_SCHM_BR NONUNIQUE
我还有一个table状态,
ACCOUNT_NUMBER VARCHAR2(16)
STATUS VARCHAR2(2)
ACCOUNT_NUMBER IDX_STATUS_ACCT UNIQUE
当我写一个连接到 table table 的查询时,如下所示,执行时间太长且查询成本高昂。
SELECT ACCOUNT_NUMBER,STATUS
FROM TEST,STATUS
where TEST.ACCOUNT_NUMBER = STATUS.ACCOUNT_NUMBER
AND TEST.BRANCH = '1000';
产品团队查询 return 以获取相同的详细信息 ||null
在 where 条件下,查询 returning 相同的结果,但
与我的查询相比,性能非常好。
SELECT ACCOUNT_NUMBER,STATUS
FROM TEST,STATUS
where TEST.ACCOUNT_NUMBER = STATUS.ACCOUNT_NUMBER
AND <b>TEST.BRANCH||NULL</b> = '1000';
任何人都可以解释一下 ||null
在 where 条件下是如何造成这种差异的。
我写这篇文章是因为,我想知道它是如何产生影响的,并且想尽可能地使用它。
如果你打开自动跟踪并获得两个查询的执行计划,我猜你的查询正在尝试使用索引 IDX_TEST_SCHM_BR
而另一个查询由于子句 [= 而无法使用索引11=] 并且不能使用索引,因为该子句阻止优化器使用索引。
通常,在 table 列上使用函数会阻止 Oracle 使用索引,在您的情况下,使用 ||
运算符将空值附加到 table 列就像调用函数 concat(TEST.BRANCH||NULL)
。要使您的查询 运行 更快,您可以
- 添加忽略索引的提示
SELECT /*+ NOINDEX(TEST1 IDX_TEST_SCHM_BR */ ACCOUNT_NUMBER, ...
(不推荐)
- 以
BRANCH
作为唯一列创建一个新索引(推荐)
正如@symcbean 指出的那样,如果索引不是很有选择性,(即:查询 returns 中 table 中的很多行),则进行完整的 table 扫描可能会更快。在这种情况下,由于 BRANCH
列不是索引中的第一列,Oracle 必须跳过索引以查找与连接条件匹配的行。 一般 的经验法则是,如果查询返回的行数超过 around 20%,则完整的 table 扫描会更快.在这种情况下,由于索引定义,Oracle 必须读取多个索引条目,一直跳过,直到找到下一个新的 BRANCH
值,因此在这种情况下,可能
不到 5%
还要确保您的 table 收集了当前的统计信息,如果您的任何列不为空,您应该在 table 定义中指定,以帮助 Oracle 优化器避免像您这样的问题有。
此查询与查询的性能调整有关。 我有一个 table TEST1,它有 200,000 行。 table 结构如下。
ACCOUNT_NUMBER VARCHAR2(16)
BRANCH VARCHAR2(10)
ACCT_NAME VARCHAR2(100)
BALANCE NUMBER(20,5)
BANK_ID VARCHAR2(10)
SCHM_CODE VARCHAR2(10)
CUST_ID VARCHAR2(10)
指标如下
fields Index Name Uniquness
ACCOUNT_NUMBER IDX_TEST_ACCT UNIQUE
SCHM_CODE,BRANCH IDX_TEST_SCHM_BR NONUNIQUE
我还有一个table状态,
ACCOUNT_NUMBER VARCHAR2(16)
STATUS VARCHAR2(2)
ACCOUNT_NUMBER IDX_STATUS_ACCT UNIQUE
当我写一个连接到 table table 的查询时,如下所示,执行时间太长且查询成本高昂。
SELECT ACCOUNT_NUMBER,STATUS
FROM TEST,STATUS
where TEST.ACCOUNT_NUMBER = STATUS.ACCOUNT_NUMBER
AND TEST.BRANCH = '1000';
产品团队查询 return 以获取相同的详细信息 ||null 在 where 条件下,查询 returning 相同的结果,但 与我的查询相比,性能非常好。
SELECT ACCOUNT_NUMBER,STATUS
FROM TEST,STATUS
where TEST.ACCOUNT_NUMBER = STATUS.ACCOUNT_NUMBER
AND <b>TEST.BRANCH||NULL</b> = '1000';
任何人都可以解释一下 ||null
在 where 条件下是如何造成这种差异的。
我写这篇文章是因为,我想知道它是如何产生影响的,并且想尽可能地使用它。
如果你打开自动跟踪并获得两个查询的执行计划,我猜你的查询正在尝试使用索引 IDX_TEST_SCHM_BR
而另一个查询由于子句 [= 而无法使用索引11=] 并且不能使用索引,因为该子句阻止优化器使用索引。
通常,在 table 列上使用函数会阻止 Oracle 使用索引,在您的情况下,使用 ||
运算符将空值附加到 table 列就像调用函数 concat(TEST.BRANCH||NULL)
。要使您的查询 运行 更快,您可以
- 添加忽略索引的提示
SELECT /*+ NOINDEX(TEST1 IDX_TEST_SCHM_BR */ ACCOUNT_NUMBER, ...
(不推荐) - 以
BRANCH
作为唯一列创建一个新索引(推荐)
正如@symcbean 指出的那样,如果索引不是很有选择性,(即:查询 returns 中 table 中的很多行),则进行完整的 table 扫描可能会更快。在这种情况下,由于 BRANCH
列不是索引中的第一列,Oracle 必须跳过索引以查找与连接条件匹配的行。 一般 的经验法则是,如果查询返回的行数超过 around 20%,则完整的 table 扫描会更快.在这种情况下,由于索引定义,Oracle 必须读取多个索引条目,一直跳过,直到找到下一个新的 BRANCH
值,因此在这种情况下,可能
还要确保您的 table 收集了当前的统计信息,如果您的任何列不为空,您应该在 table 定义中指定,以帮助 Oracle 优化器避免像您这样的问题有。