讲师中心 微信公众号
AI工具推荐 视频效率加速

为什么EF Core对Oracle生成的SQL效率极低

夏浩君_1880

夏浩君_1880

发布时间:2026-10-01 10:29:17

|

124人浏览过

|

来源于php中文网

原创

根本原因是Oracle优化器对ROWNUM分页的天然限制:外层ROWNUM无法下推至索引扫描阶段,必须先取全部结果再裁剪;叠加ORDER BY字段无索引或被NLSSORT隐式包裹时,极易触发全表扫描。

为什么ef core对oracle生成的sql效率极低

EF Core 对 Oracle 生成的 SQL 效率低,根本原因不是 EF Core 写得差,而是它默认的分页和排序机制撞上了 Oracle 优化器的几个硬限制——尤其是 ROWNUM 嵌套、NLSSORT 隐式包裹、以及缺失索引提示这三者叠加时,执行计划里几乎必出 full table scan。

为什么 Skip/Take 在 Oracle 上会触发全表扫描

EF Core 的 Skip()/Take() 在 Oracle Provider 下默认翻译为两层子查询:外层用 ROWNUM 截断,内层先 <code>ORDER BY。但 Oracle 无法把 ROWNUM 条件下推到索引扫描阶段,必须先把全部排序结果算出来,再裁剪——数据量一过百万,I/O 和内存压力就陡增。

常见错误现象:

  • 执行计划中出现 VIEW + SORT ORDER BY + COUNT STOPKEY,且 ROWS 列远大于实际返回行数
  • 即使 ORDER BY 字段有索引,执行计划仍显示 INDEX FULL SCAN 或 TABLE ACCESS FULL

关键原因:

  • ORDER BY name 实际被 Oracle Provider 自动转成 ORDER BY NLSSORT(name, 'NLS_SORT=BINARY')(受连接字符串或会话级 NLS_SORT 影响)
  • 而你建的普通索引对 NLSSORT() 函数无效,必须显式建函数索引:CREATE INDEX idx_orders_name_binary ON orders (NLSSORT(name, 'NLS_SORT=BINARY'))

如何确认是不是 NLS 参数惹的祸

直接查当前会话的 NLS 设置比看文档更快:

SELECT * FROM NLS_SESSION_PARAMETERS WHERE PARAMETER IN ('NLS_SORT', 'NLS_COMP');

如果返回 NLS_SORT = 'LINGUISTIC' 或 NLS_COMP = 'ANSI',基本可以锁定问题——EF Core 生成的排序语句会被强制套上 NLSSORT(),导致索引失效。

Crypto Sniper Oracle
Crypto Sniper Oracle

机构级量化市场预言机,提供订单簿失衡(OBI)、VWAP分析、自动化报告及Telegram预警。

下载

临时验证方法(在 SQL*Plus 或 SQL Developer 中执行):

  • 手动运行 EF Core 日志里捕获到的原始 SQL,观察执行计划
  • 再运行等价的“去 NLS 化”版本:SELECT * FROM (SELECT /*+ INDEX(t idx_name_binary) */ ..., ROWNUM rnum FROM (SELECT ... ORDER BY name) t) WHERE rnum > 10 AND rnum <= 20
  • 对比两次的 Cost 和 Bytes —— 差异超过 10 倍,就是 NLS 拖累

绕过 ROWNUM 分页的三个实操选择

不是所有场景都适合改写 SQL,但以下方案可落地:

  • 小数据量(< 5k 行):加 AsNoTracking() + Select() 投影,减少内存拷贝开销,但不解决分页本身
  • 中等数据量(5k–100k):在 DbContext 构造时显式设置会话级 NLS:connection.Execute("ALTER SESSION SET NLS_SORT = 'BINARY'");
  • 大数据量(> 100k):放弃 Skip/Take,改用游标分页(keyset pagination),例如按 id DESC + WHERE id < @lastId,配合覆盖索引 CREATE INDEX idx_orders_id_desc ON orders (id DESC)

注意:Oracle 12c+ 支持 OFFSET/FETCH,但 EF Core Oracle Provider(如 Oracle.EntityFrameworkCore 7.x)默认仍走 ROWNUM 路径,需手动切换 Provider 或用 FromSqlRaw 强制。

最容易被忽略的索引陷阱

很多人建了索引还慢,是因为只建了字段索引,没管排序方向和函数封装:

  • ORDER BY created_at DESC 需要反向索引:CREATE INDEX idx_orders_created_desc ON orders (created_at DESC),普通升序索引效果差
  • WHERE status = 'paid' ORDER BY id 这种组合,单列索引无效,得建联合索引且顺序匹配:CREATE INDEX idx_orders_status_id ON orders (status, id)
  • 用了 AsNoTracking() 却忘了 Select() 投影——EF Core 仍会加载整行字段,网络和序列化开销照旧

真正卡住性能的,往往不是 EF Core 本身,而是 Oracle 会话参数、索引定义、以及分页模型三者之间那几毫米的错位。

热门AI工具

更多
豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

UP简历
UP简历 Hot

一款AI办公效率工具,主要用于基于AI技术的免费在线简历制作工具,适合需要提升相关任务效率的用户。

UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

超级简历WonderCV

一款AI办公效率工具,主要用于免费求职简历模版下载制作,应届生职场人必备简历制作神器,适合需要提升相关任务效率的用户。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

LibLibAI
LibLibAI Hot

一款AI视频创作工具,主要用于国内领先的AI创意平台,以海量模型、低门槛操作与“创作-分享-商业化”生态,让小白与专业创作者都能高效实现图文乃至视频创意表达,适合需要提升相关任务效率的用户。

Seko
Seko Hot

一款AI视频创作工具,主要用于商汤科技推出的创编一体的AI短视频创作Agent,适合需要提升相关任务效率的用户。

AionClaw
AionClaw Hot

AionClaw是一款面向办公、创作和编程任务的AI桌面智能体。

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

3883

2023.10.12

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

831

2023.10.27

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

1009

2024.02.23

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

5721

2024.03.06

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

2683

2024.03.06

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

5700

2024.04.07

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

7521

2024.04.29

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

1030

2024.04.29

LLVM自定义Pass怎么写
LLVM自定义Pass怎么写

本专题聚焦LLVM自定义Pass开发,整理Pass类结构、run()方法、PreservedAnalyses、CMake构建、插件注册、-load-pass-plugin加载和测试用例编写流程。

0

2026.09.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn