oracle count 1 原理,count(1)是否走索引?

1.都可以

2.会

3.会

只要是非空且有index的话就可以~

还可以扩展一下如果是没有非空约束但是有index的话

select  count(object_id) from test;

这个也是可以走index的~

也就是说count(*)和count(column name)是不一样的

SQL> select count(4) from test;

Execution Plan

----------------------------------------------------------

Plan hash value: 1233762146

------------------------------------------------------------------------------

| Id  | Operation             | Name         | Rows  | Cost (%CPU)| Time     |

------------------------------------------------------------------------------

|   0 | SELECT STATEMENT      |              |     1 |    25   (4)| 00:00:01 |

|   1 |  SORT AGGREGATE       |              |     1 |            |          |

|   2 |   INDEX FAST FULL SCAN| OBJ_ID_INDEX | 42524 |    25   (4)| 00:00:01 |

------------------------------------------------------------------------------

Note

-----

- dynamic sampling used for this statement

Statistics

----------------------------------------------------------

249  recursive calls

0  db block gets

240  consistent gets

0  physical reads

0  redo size

517  bytes sent via SQL*Net to client

487  bytes received via SQL*Net from client

2  SQL*Net roundtrips to/from client

5  sorts (memory)

0  sorts (disk)

1  rows processed

SQL> select count(*) from test;

Execution Plan

----------------------------------------------------------

Plan hash value: 1233762146

------------------------------------------------------------------------------

| Id  | Operation             | Name         | Rows  | Cost (%CPU)| Time     |

------------------------------------------------------------------------------

|   0 | SELECT STATEMENT      |              |     1 |    25   (4)| 00:00:01 |

|   1 |  SORT AGGREGATE       |              |     1 |            |          |

|   2 |   INDEX FAST FULL SCAN| OBJ_ID_INDEX | 42524 |    25   (4)| 00:00:01 |

------------------------------------------------------------------------------

Note

-----

- dynamic sampling used for this statement

Statistics

----------------------------------------------------------

4  recursive calls

0  db block gets

168  consistent gets

0  physical reads

0  redo size

517  bytes sent via SQL*Net to client

487  bytes received via SQL*Net from client

2  SQL*Net roundtrips to/from client

0  sorts (memory)

0  sorts (disk)

1  rows processed

SQL> desc test;

Name                                      Null?    Type

----------------------------------------- -------- ----------------------------

OWNER                                     NOT NULL VARCHAR2(30)

OBJECT_NAME                               NOT NULL VARCHAR2(30)

SUBOBJECT_NAME                                     VARCHAR2(30)

OBJECT_ID                                 NOT NULL NUMBER

DATA_OBJECT_ID                                     NUMBER

OBJECT_TYPE                                        VARCHAR2(19)

CREATED                                   NOT NULL DATE

LAST_DDL_TIME                             NOT NULL DATE

TIMESTAMP                                          VARCHAR2(19)

STATUS                                             VARCHAR2(7)

TEMPORARY                                          VARCHAR2(1)

GENERATED                                          VARCHAR2(1)

SECONDARY                                          VARCHAR2(1)

<think>好的,我现在需要帮助用户验证他们的Oracle分页查询语句的正确性,并确认分页逻辑是否正确。用户还提到了参数绑定在@Query注解中的应用,我需要结合之前的引用和JPA的最佳实践来回答。 首先,用户提供的SQL查询使用了ROWNUM进行分页,这是Oracle中常用的方法。我需要检查这个查询的结构是否符合Oracle的分页标准。通常,Oracle分页是通过子查询和ROWNUM来实现的,用户的结构看起来是正确的,外层和内层子查询分别处理行号,并且使用了别名来正确引用ROWNUM。 接下来,参数绑定部分,用户使用了命名参数:pageSize、:pageNum和:hospitalNme。在JPA中,命名参数是支持的,但需要确保在@Query注解中正确使用@Param来绑定参数。用户的代码示例中确实使用了@Param,所以这部分看起来没问题。不过需要提醒用户参数注入的风险,确保没有SQL注入的可能,比如医院名称的模糊查询使用了连接符,但JPA的参数绑定通常能处理这些,只要不直接拼接字符串。 然后,分页逻辑的正确性。用户的分页公式是否正确?例如,计算起始行号是否(:pageNum - 1) * :pageSize +1,而结束行号是:pageNum * :pageSize。不过用户当前的查询中使用的是WHERE rnum >= ((:pageNum -1)*:pageSize),这可能有问题,因为ROWNUM是从1开始的,正确的结束行号应该是:pageNum * :pageSize,而起始行号是(:pageNum -1)*:pageSize +1。用户的当前条件可能漏掉了+1,导致分页偏移不正确,比如第一页可能从0开始,这不符合ROWNUM的起始值,需要指出这一点。 另外,用户没有使用countQuery,这会导致分页的总记录数查询可能效率低下,特别是当主查询复杂时。需要建议用户添加countQuery来优化计数查询,提升性能。 还需要考虑数据库方言的问题,确保JPA配置正确使用Oracle方言,以避免分页语法错误。同时,参数绑定的类型是否正确,比如pageNum和pageSize是否为整数,避免类型不匹配的错误。 最后,建议用户进行实际测试,检查返回的分页数据是否符合预期,特别是在边界情况如第一页和最后一页。同时,提醒使用PageHelper等工具可能带来的便利,但需要根据项目实际情况选择合适的分页方法。</think>根据您提供的SQL查询和Oracle分页实现要求,现从语法、参数绑定、分页逻辑三个维度进行分析: ### 一、Oracle分页语法验证 #### 1. 标准ROWNUM分页结构 Oracle分页推荐使用双重嵌套子查询: ```sql SELECT * FROM ( SELECT a.*, ROWNUM rnum FROM ( -- 核心查询语句 SELECT * FROM gl_hospital WHERE (:hospitalNme IS NULL OR HOSPITAL_NME LIKE '%' || :hospitalNme || '%') ORDER BY HOSPITAL_CDE ) a WHERE ROWNUM <= :pageNum * :pageSize -- 结束行号 ) WHERE rnum >= ((:pageNum - 1) * :pageSize) + 1 -- 起始行号 ``` *对比发现原查询缺少`+1`偏移量,可能导致起始行号计算错误[^1]* #### 2. 当前查询存在问题 ```sql WHERE rnum >= ((:pageNum - 1) * :pageSize) ``` 错误示例:当pageNum=2、pageSize=10时: - 当前逻辑:rnum >= 10 - 正确逻辑:rnum >= 11 ### 二、参数绑定验证 #### 1. 命名参数正确性 ```java @Query(nativeQuery = true, value = "...") List<HospitalEntity> selectAll( @Param("pageSize") Integer pageSize, @Param("pageNum") Integer pageNum, @Param("hospitalNme") String hospitalNme ); ``` 参数绑定符合JPA规范,但需注意: - 参数类型必须匹配(pageSize/pageNum应为Integer) - 模糊查询应使用`CONCAT('%', :hospitalNme, '%')`更规范[^2] #### 2. 分页参数范围校验 建议添加参数校验逻辑: ```java if (pageNum < 1 || pageSize < 1) { throw new IllegalArgumentException("分页参数必须大于0"); } ``` ### 三、改进建议 #### 1. 修正后的分页SQL ```sql SELECT * FROM ( SELECT a.*, ROWNUM rnum FROM ( SELECT * FROM gl_hospital WHERE (:hospitalNme IS NULL OR HOSPITAL_NME LIKE CONCAT(CONCAT('%', :hospitalNme), '%')) ORDER BY HOSPITAL_CDE ) a WHERE ROWNUM <= :pageNum * :pageSize ) WHERE rnum >= ((:pageNum - 1) * :pageSize) + 1 ``` #### 2. 添加countQuery(必须) ```java @Query(value = "修正后的主查询SQL", countQuery = "SELECT COUNT(*) FROM gl_hospital WHERE (:hospitalNme IS NULL OR HOSPITAL_NME LIKE CONCAT(CONCAT('%', :hospitalNme), '%'))", nativeQuery = true) Page<HospitalEntity> selectAll(...); ``` #### 3. 性能优化建议 - 为HOSPITAL_NME列建立函数索引: ```sql CREATE INDEX idx_hospital_name ON gl_hospital(UPPER(HOSPITAL_NME)); ``` - 使用绑定变量提示: ```sql /*+ BIND_AWARE */ ``` ### 四、验证方法 1. **执行计划分析** ```sql EXPLAIN PLAN FOR 修正后的SQL; SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY); ``` 检查是否索引是否出现全表扫描 2. **边界测试用例** | pageNum | pageSize | 预期结果行数 | |---------|----------|-------------| | 1 | 10 | 10 | | 2 | 20 | 20 | | 0 | 10 | 抛出异常 |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值