【发布时间】:2016-09-30 08:51:26
【问题描述】:
我有一个场景,我需要从包含大量行的大表中搜索和显示记录。我为我的表预先定义了搜索条件,用户可以为其提供过滤器并单击搜索。
考虑一个示例表:
CREATE TABLE suppliers
( supplier_name varchar2(50) NOT NULL,
address varchar2(50),
city varchar2(50) NOT NULL,
state varchar2(25),
zip_code varchar2(10),
CONSTRAINT "suppliers_pk" PRIMARY KEY (supplier_name, city)
);
INSERT INTO suppliers VALUES ('ABCD','XXXX','YYYY','ZZZZ','95012');
INSERT INTO suppliers VALUES ('EFGH','MMMM','NNNN','OOOO','95010');
INSERT INTO suppliers VALUES ('IJKL','EEEE','FFFF','GGGG','95009');
我已经为用户提供了搜索字段作为主键 - 供应商名称,城市
如果他输入两个字段,我的查询性能会很好,因为它用于索引扫描
SELECT supplier_name, address, city, state, zip_code FROM suppliers where supplier_name = 'ABCD' and city = 'ZZZZ';
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 102 | 1 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| SUPPLIERS | 1 | 102 | 1 (0)| 00:00:01 |
|* 2 | INDEX UNIQUE SCAN | suppliers_pk | 1 | | 1 (0)| 00:00:01 |
但是,如果他只输入其中一个搜索字段,我的查询性能会变差,因为它用于全表扫描
SELECT supplier_name, address, city, state, zip_code FROM suppliers where supplier_name = 'ABCD' ;
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 102 | 3 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| SUPPLIERS | 1 | 102 | 3 (0)| 00:00:01 |
当我在搜索中没有所有关键字段时,有没有办法强制 oracle 认为它是主键搜索,如下所示(这显然不起作用)
SELECT supplier_name, address, city, state, zip_code FROM suppliers where supplier_name = 'ABCD' and city = city;
谢谢。
【问题讨论】:
-
Oracle 可能会执行跳过扫描索引搜索,如果它认为这比全表扫描更合适且更有效。一般来说,假设统计数据是最新的,优化器非常擅长使用可用索引选择最佳计划。如果它认为它不能进行跳过扫描,也许您需要在
city上建立一个单独的索引?让它使用 PK 索引不太可能是有效的 - 它可能会进行完整的索引扫描,然后仍然必须获取相关行的数据块。 -
您的表中只有 3 行。添加 10 000 行,收集统计数据并分析结果。
-
谢谢,我确实在一张有数百万行的表上进行了尝试,它进行的是 INDEX RANGE SCAN 而不是 FTS。
标签: oracle composite-primary-key