【发布时间】:2014-12-05 10:25:30
【问题描述】:
我想知道为什么这个查询的成本
select * from address a
left join name n on n.adress_id=a.id
where a.street='01';
高于
select * from address a
left join name n on n.adress_id=a.id
where a.street=N'01';
地址表如下所示
ID NUMBER
STREET VARCHAR2(255 CHAR)
POSTAL_CODE VARCHAR2(255 CHAR)
名称表是这样的
ID NUMBER
ADDRESS_ID NUMBER
NAME VARCHAR2(255 CHAR)
SURNAME VARCHAR2(255 CHAR)
这些是解释计划返回的成本
解释“01”的计划
-----------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 3591 | 1595K| 87 (0)| 00:00:02 |
| 1 | NESTED LOOPS OUTER | | 3591 | 1595K| 87 (0)| 00:00:02 |
|* 2 | TABLE ACCESS FULL | ADDRESS | 3 | 207 | 3 (0)| 00:00:01 |
| 3 | TABLE ACCESS BY INDEX ROWID| NAME | 1157 | 436K| 47 (0)| 00:00:01 |
|* 4 | INDEX RANGE SCAN | NAME_HSI | 1157 | | 1 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("A"."STREET"='01')
4 - access("N"."ADDRESS_ID"(+)="A"."ID")
解释 N'01' 的计划
-----------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 347 | 154K| 50 (0)| 00:00:01 |
| 1 | NESTED LOOPS OUTER | | 347 | 154K| 50 (0)| 00:00:01 |
|* 2 | TABLE ACCESS FULL | ADDRESS | 1 | 69 | 3 (0)| 00:00:01 |
| 3 | TABLE ACCESS BY INDEX ROWID| NAME | 1157 | 436K| 47 (0)| 00:00:01 |
|* 4 | INDEX RANGE SCAN | NAME_HSI | 1157 | | 1 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(SYS_OP_C2C("A"."STREET")=U'01')
4 - access("N"."ADDRESS_ID"(+)="A"."ID")
如您所见,N'01' 查询的成本低于 '01' 的成本。知道为什么吗? N'01' 需要另外将 varchar 转换为 nvarchar,因此成本应该更高(SYS_OP_C2C())。另一个问题是为什么N'01'查询处理的行数低于'01'?
[编辑]
- 表
address有 30 行。 - 表
name有 19669 行。
【问题讨论】:
-
你能把两张表的行数都贴出来吗?
-
@realspirituals 看到我的编辑。
-
您是否收集了有关表格的统计信息?这里最大的不同是优化器猜测地址表中的 3 行满足
street='01',但只有 1 行满足street=N'01'。第一种情况优化器使用适合相等谓词的基数估计算法,另一种情况优化器看到一个函数应用于表中的列,这意味着它必须猜测 - 可能猜测“大约 5% 的行数桌子。” -
@KimBergHansen,我不是 SQL 开发人员,所以我什至不知道如何存储表统计信息(顺便说一句,我该如何检查它?它是否存储在 db 中的某个位置?)。
-
收集统计数据不会产生任何影响。无论如何都会应用内部函数,并且两个不同应用的过滤器的基数估计会有所不同。