在搜索期间强制在 Oracle 中使用主键

Force use of primary key in Oracle during search

我有这样的场景,我需要搜索和显示来自大量 table 的大量行的记录。我为我的 table 预定义了搜索条件,用户可以为其提供过滤器并点击搜索。

考虑样本 table :

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');

我已经为用户提供了搜索字段作为主键 - supplier_name,城市

如果他输入两个字段,我的查询性能会很好,因为它用于索引扫描

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 |

但是,如果他只输入一个搜索字段,我的查询性能会变差,因为它会进行完整 table 扫描

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;

谢谢。

完整的table 扫描不一定是坏的。您的 table 中只有几行,因此优化器认为执行 FTS 比索引范围扫描更好。一旦 RDBMS 认为它更好,它将立即开始使用 PK 索引,即你有很多行并且对某个供应商的限制显着降低了结果。如果你只想搜索城市而不是供应商,你需要另一个只包含城市的索引(或者至少从城市开始)。请记住,您可能需要在 table 加载批量数据后更新 table 统计数据。使用实际数量的数据测试查询性能始终很重要。

索引首先在 supplier_name 上组织,其次在城市上组织,因此无法将该索引用于仅基于城市的查询。 请仅基于城市创建第二个索引。这将有助于您的查询。

你的想法是错误的。

查询优化器将根据解析查询时(或有时参数更改时)可用的信息选择它认为最佳的查询执行计划。一般来说——如果你在统计等方面给它正确的信息,它通常会做得很好。

您可能认为自己比它更了解,但请记住,您不会在数据库的整个生命周期内监视它。数据发生变化,您希望数据库能够在需要时做出反应并更改执行计划。

也就是说,如果您设置为强制它使用索引,您可以使用提示:

SELECT /*+ INDEX(suppliers suppliers_pk) */
supplier_name, address, city, state, zip_code FROM suppliers where   
supplier_name = 'ABCD' ;