当前位置: 首页 > article >正文

Oracle 迁移 PostgreSQL 踩坑:ROWNUM 与 DISTINCT 执行顺序差异导致 SQL 结果不一致

文章目录引言一次诡异的数据丢失排查一、现象复现同样的 SQL不同的结果在 KES / Oracle 中的执行过程在 PostgreSQL 中的执行过程二、原理剖析执行优先级的致命差异2.1 KES / OracleROWNUM 的先截后去2.2 PostgreSQLLIMIT 的先去后截2.3 执行计划差异ROWNUM 阻断子查询提升三、避坑指南如何写出跨库一致的 SQL方案一嵌套子查询推荐方案二明确你的业务意图方案三使用窗口函数最精确的控制四、总结同样一条 SQL换个数据库跑行数不一样了。这不是玄学是执行优先级的锅。引言一次诡异的数据丢失排查上周一位从 Oracle 迁移到金仓数据库 KES 的开发者在群里抛出一个问题“我的查询明明写了ROWNUM 10为什么返回的结果有时候是 7 行、8 行就是不到 10 行而且同样的 SQL 在同事的 PostgreSQL 上跑偏偏返回的就是 10 行。”他跑的 SQL 是这样的SELECTDISTINCTuser_idFROMaccess_logWHERErownum10;access_log表存储的是用户访问日志同一个user_id可能出现在多行中。他的本意是取前 10 个不重复的用户。但实际结果却让人困惑。如果你也遇到过类似的问题或者你正在从 Oracle 迁移到 KES / PostgreSQL这篇文章将帮你彻底理清背后的执行优先级差异避免在后续开发中踩同样的坑。一、现象复现同样的 SQL不同的结果让我们用一个简单的数据集来复现这个现象。假设access_log表的前 15 行数据如下rowiduser_id1A2A3B4C5A6D7E8B9F10G11H12C13I14J15K执行SELECT DISTINCT user_id FROM access_log WHERE rownum 10;时在 KES / Oracle 中的执行过程先取 10 行扫描前 10 行物理记录rowid 1-10后去重对这 10 行做DISTINCT得到 A、B、C、D、E、F、G结果7 行而非 10 行在 PostgreSQL 中的执行过程PG 使用LIMIT而非ROWNUM等价 SQL 为SELECT DISTINCT user_id FROM access_log LIMIT 10;先去重对全表做DISTINCT得到所有不重复的 user_id后取 10 行对去重后的结果取前 10 个结果10 行恰好 10 个不重复 user_id二、原理剖析执行优先级的致命差异2.1 KES / OracleROWNUM 的先截后去在 KES 和 Oracle 中ROWNUM是一个动态生成的伪列。它的赋值发生在数据读取阶段早于DISTINCT、ORDER BY等操作。执行顺序可以概括为全表扫描 → 逐行赋予 ROWNUM → 过滤 ROWNUM 条件 → DISTINCT 去重 → 返回结果关键问题在于ROWNUM 10在去重之前就截断了数据。如果前 10 行物理记录中存在大量重复值去重后的结果自然会少于 10 行。用流程图表述原始 10 行: A A B C A D E B F G ↓ DISTINCT 去重 结果 7 行: A B C D E F G2.2 PostgreSQLLIMIT 的先去后截PostgreSQL 的LIMIT作用于最终结果集。执行顺序为全表扫描 → DISTINCT 去重 → LIMIT 截取前 N 行 → 返回结果这种语义更符合大多数开发者的直觉——“我要 10 个不重复的值”。2.3 执行计划差异ROWNUM 阻断子查询提升更深入地说ROWNUM的存在还会影响优化器的决策。在 KES / Oracle 中当子查询内部引用了ROWNUM时外部查询的过滤条件无法下推到子查询中这一优化技术称为子查询提升或Pull-up。这意味着SELECT*FROM(SELECTDISTINCTuser_idFROMaccess_logWHERErownum10)tWHEREt.user_idA;在这条 SQL 中WHERE t.user_id A这个外部过滤条件无法被下推到子查询内部。优化器被迫先对子查询做全表扫描取前 10 行然后在外层做过滤。如果数据量很大这可能导致不必要的性能损耗。相比之下如果将ROWNUM替换为LIMITPostgreSQL 的优化器通常可以将外部条件下推从而减少扫描范围。三、避坑指南如何写出跨库一致的 SQL方案一嵌套子查询推荐如果你确实需要先取 N 行再去重的 Oracle / KES 语义但希望在 PG 上得到一致结果使用嵌套子查询-- KES / Oracle / PG 均可执行行为一致SELECTDISTINCTuser_idFROM(SELECTuser_idFROMaccess_logWHERErownum10)t;或者在 PG 中SELECTDISTINCTuser_idFROM(SELECTuser_idFROMaccess_logLIMIT10)t;方案二明确你的业务意图问自己一个问题你的业务到底想要什么业务意图KES / Oracle 写法PG 写法取前 N 行物理记录然后去重SELECT DISTINCT ... WHERE rownum N用子查询 LIMIT取 N 个不重复的值嵌套子查询 或ROW_NUMBER()SELECT DISTINCT ... LIMIT N大多数情况下开发者的真实意图是后者——“我要 N 个不重复的值”。在这种情况下KES / Oracle 中的DISTINCT ROWNUM组合其实是写错了。方案三使用窗口函数最精确的控制如果你需要对排序、去重、截断的顺序有完全精确的控制使用窗口函数是最可靠的方式-- 先按 user_id 分组取每个 user_id 的最小 rowid然后取前 10 个SELECTuser_idFROM(SELECTuser_id,ROW_NUMBER()OVER(ORDERBYMIN(rowid))ASrnFROMaccess_logGROUPBYuser_id)tWHERErn10;这种写法在所有数据库中行为一致且语义最为明确。四、总结DISTINCT ROWNUM的执行优先级陷阱本质上是不同数据库对行号伪列赋值时机的设计差异。关键要点回顾KES / OracleROWNUM赋值在DISTINCT之前——先截取后去重结果可能少于 N 行。PostgreSQLLIMIT作用于最终结果——先去重后截取结果恰好 N 行。ROWNUM 阻断子查询提升引用ROWNUM的子查询外部过滤条件无法下推可能导致全表扫描。最佳实践明确业务意图选择正确的写法跨库兼容场景下使用嵌套子查询或窗口函数避免将DISTINCT ROWNUM作为取 N 个不重复值的手段记住一条铁律永远不要用ROWNUM去做你真正想做之外的事情。它的行为高度依赖于它在 SQL 中的位置和数据库引擎的实现细节。当你对执行顺序有一丝不确定时窗口函数永远是最安全的选择。本文基于金仓数据库 KingbaseES V9 / Oracle 19c / PostgreSQL 15 编写。

相关文章:

Oracle 迁移 PostgreSQL 踩坑:ROWNUM 与 DISTINCT 执行顺序差异导致 SQL 结果不一致

文章目录引言:一次诡异的"数据丢失"排查一、现象复现:同样的 SQL,不同的结果在 KES / Oracle 中的执行过程在 PostgreSQL 中的执行过程二、原理剖析:执行优先级的致命差异2.1 KES / Oracle:ROWNUM 的"先…...

5分钟快速上手:用TMSpeech实现Windows离线语音转文字,保护隐私的会议记录神器

5分钟快速上手:用TMSpeech实现Windows离线语音转文字,保护隐私的会议记录神器 【免费下载链接】TMSpeech 腾讯会议摸鱼工具 项目地址: https://gitcode.com/gh_mirrors/tm/TMSpeech 还在为线上会议记录手忙脚乱吗?担心语音数据上传云端…...

从桌面玩具到生产力工具:Dobot Magician机械臂的5个超实用项目实战(含代码)

从桌面玩具到生产力工具:Dobot Magician机械臂的5个超实用项目实战(含代码) 在创客圈里积灰的Dobot Magician机械臂,可能正等待一次真正的觉醒。这款被许多人当作"高级玩具"的六轴机械臂,实际上隐藏着足以改…...

《AUTOSAR软件组件(SWC)实战:基于ETAS工具链的接口与数据映射》

1. AUTOSAR软件组件(SWC)基础概念 在汽车电子开发领域,AUTOSAR(汽车开放系统架构)已经成为行业标准。软件组件(SWC)作为AUTOSAR架构中的核心元素,承担着实现具体功能的重任。简单来说,SWC就像乐高积木,每个…...

【C++】继承详解——基类/派生类、作用域、默认函数、菱形继承(超详细)

文章目录一、继承开篇二、继承的概念及定义1. 继承是什么2. 继承定义格式3. 继承后成员访问权限变化(超级重要)三、基类和派生类的赋值转换(切片/切割)四、继承中的作用域(隐藏 / 重定义)1. 成员变量隐藏2.…...

Loop:Mac免费窗口管理神器,彻底告别桌面混乱的终极解决方案

Loop:Mac免费窗口管理神器,彻底告别桌面混乱的终极解决方案 【免费下载链接】Loop Window management made elegant. 项目地址: https://gitcode.com/GitHub_Trending/lo/Loop 你是否曾因Mac桌面上堆满的窗口而感到困扰?当多个应用程序…...

终极NS模拟器管理工具:三分钟搞定Switch模拟器安装配置

终极NS模拟器管理工具:三分钟搞定Switch模拟器安装配置 【免费下载链接】ns-emu-tools 一个用于安装/更新 NS 模拟器的工具 项目地址: https://gitcode.com/gh_mirrors/ns/ns-emu-tools 还在为复杂的Switch模拟器安装配置而头疼吗?NsEmuTools是你…...

为OpenClaw智能体工作流配置Taotoken作为后端模型供应商

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 为OpenClaw智能体工作流配置Taotoken作为后端模型供应商 对于使用OpenClaw框架构建AI智能体的开发者而言,将后端模型服…...

4 个新的流行 AI 概念及其在数字产品中的潜力

原文:towardsdatascience.com/the-4-new-trendy-ai-concepts-and-their-potential-in-digital-products-cf5e1b85bff9 https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/79c8534a324cff796ff9200cb0207d8a.png 图片由Joshua Col…...

给SATA硬盘下命令:从Non-Data到DMA Queued,12类命令的实战图解与抓包分析

深入解析SATA硬盘12类命令:从Non-Data到DMA Queued的实战指南 在存储系统的底层交互中,SATA协议扮演着至关重要的角色。对于嵌入式开发工程师和存储系统测试人员而言,理解SATA命令层的运作机制不仅有助于调试硬件问题,更能优化存储…...

自主AI助手Angel:基于大语言模型的多通道智能体部署与实战

1. 项目概述:一个能帮你“跑腿”的自主AI助手如果你和我一样,经常在Discord、Slack、iMessage和Signal这几个聊天软件之间来回切换,同时电脑上还开着十几个终端窗口处理各种杂事,那你肯定幻想过能有一个“数字管家”。它最好能看懂…...

点云配准避坑指南:当ICP把深度图配到‘中心’时,我的自适应阈值调整方案

点云配准避坑指南:动态阈值优化解决ICP中心化失效问题 在三维重建和SLAM项目中,工程师们常常会遇到一个令人头疼的现象:使用标准ICP算法对深度图点云进行配准时,点云会神秘地"滑向"彼此的中心位置。这种看似魔法的行为背…...

Zotero PDF Translate:打破语言壁垒,让外文文献阅读更高效 [特殊字符]

Zotero PDF Translate:打破语言壁垒,让外文文献阅读更高效 🚀 【免费下载链接】zotero-pdf-translate Translate PDF, EPub, webpage, metadata, annotations, notes to the target language. Support 20 translate services. 项目地址: ht…...

Process Explorer|微软官方免费进程神器|吊打系统任务管理器|揪出隐藏恶意软件

电脑莫名卡顿、风扇狂转、文件删不掉?系统任务管理器查不到元凶?试试 Process Explorer—— 微软官方免费进程管理工具,功能碾压自带任务管理器,轻松揪出后台隐藏恶意软件,普通用户也能上手! 备用下载 一…...

AI智能体编排框架实战:构建具备记忆与协作能力的智能系统

1. 项目概述:当AI智能体需要“记忆”与“协作”在AI智能体开发领域,我们常常面临一个核心挑战:如何让智能体不仅能在单次对话中表现出色,还能记住历史、规划未来,并与其他智能体协同工作?这就像组建一支足球…...

终极指南:如何在OBS中集成专业VST插件实现广播级音频处理

终极指南:如何在OBS中集成专业VST插件实现广播级音频处理 【免费下载链接】obs-vst Use VST plugins in OBS 项目地址: https://gitcode.com/gh_mirrors/ob/obs-vst OBS-VST是一个革命性的开源项目,它让OBS Studio用户能够直接加载和使用数千种VS…...

硬件工程师差旅数据安全与设备防护全攻略

1. 一次旅行噩梦引发的硬件工程师深度思考那次在曼彻斯特机场洗手间里,背包从门上一个简陋的金属挂钩上滑落,发出那声令人心悸的“咔嚓”声时,我脑子里闪过的第一个念头不是“我的电脑完了”,而是“完了,我所有的设计文…...

NCE外汇:平台稳定性与用户体验的全面观察

金融服务行业的复杂性决定了平台需要在多个维度上同时具备较高的水准。NCE外汇经过多年的发展,已经在合规、技术、服务、教育等方面形成了一套相互支撑的体系。本文从评测视角出发,对其综合实力进行多维度的解读,呈现一个具有结构感的平台画像…...

LaTeX公式转换终极指南:3分钟搞定Word数学公式的免费Chrome扩展

LaTeX公式转换终极指南:3分钟搞定Word数学公式的免费Chrome扩展 【免费下载链接】LaTeX2Word-Equation Copy LaTeX Equations as Word Equations, a Chrome Extension 项目地址: https://gitcode.com/gh_mirrors/la/LaTeX2Word-Equation 还在为学术论文中复杂…...

如何用XiaoMusic让小爱音箱变身你的私人音乐管家:5个超实用场景解析

如何用XiaoMusic让小爱音箱变身你的私人音乐管家:5个超实用场景解析 【免费下载链接】xiaomusic 使用小爱音箱播放音乐,音乐使用 yt-dlp 下载。 项目地址: https://gitcode.com/GitHub_Trending/xia/xiaomusic 还在为小爱音箱只能播放特定平台的音…...

ClickHouse:开源数据引擎在AI浪潮爆发,挑战传统数据库巨头

ClickHouse:开源数据引擎爆发,在AI浪潮中挑战传统数据库巨头过去18个月,开源数据基础设施里最热的公司除了Supabase可能就是ClickHouse了。ClickHouse Cloud ARR在2025年保持250%的同比增速,第三方估计从2024年中的约1500万美元增…...

如何在Mac上免费实现NTFS磁盘完整读写:终极解决方案指南

如何在Mac上免费实现NTFS磁盘完整读写:终极解决方案指南 【免费下载链接】Free-NTFS-for-Mac Nigate: An open-source NTFS utility for Mac. It supports all Mac models (Intel and Apple Silicon), providing full read-write access, mounting, and management …...

为AI助手打造企业级FTP/SFTP操作引擎:告别重复脚本,实现智能文件部署

1. 项目概述:为AI助手量身打造的FTP/SFTP操作引擎如果你和我一样,经常让AI助手(比如Claude、Cursor、Windsurf)帮忙写代码、部署项目,那你肯定遇到过这个让人哭笑不得的场景:AI能帮你从零开始配置一台VPS&a…...

如何优雅地从九大网盘获取真实下载地址:一个JavaScript工具的深度解析

如何优雅地从九大网盘获取真实下载地址:一个JavaScript工具的深度解析 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 / 中国…...

微信小程序逆向工程:wxappUnpacker技术深度解析与实战指南

微信小程序逆向工程:wxappUnpacker技术深度解析与实战指南 【免费下载链接】wxappUnpacker forked from https://github.com/qwerty472123/wxappUnpacker 项目地址: https://gitcode.com/gh_mirrors/wxappu/wxappUnpacker 微信小程序逆向分析是理解小程序架构…...

Android开源生态重构:从中心化控制到社区驱动的技术路径与挑战

1. 从“相对开放”到“真正自由”:Android生态的十字路口作为一名在移动通信和嵌入式系统领域摸爬滚打了十几年的工程师,我亲眼见证了Android从初代HTC Dream上那个略显笨拙的“小绿人”,成长为如今驱动全球数十亿智能设备的庞然大物。最近重…...

新手必看:PCB设计全流程详解

1、画原理图不会画就先抄板子设计-更新转化为PCB2、画PCB(1)大概整理好之后自动布线GND不连(2)铺铜 (顶层和底层都铺)(3)DRC检查解决问题-重建铺铜区3、丝印层添加文字4、最后一步一…...

Logisim-evolution终极指南:从数字电路新手到硬件设计高手

Logisim-evolution终极指南:从数字电路新手到硬件设计高手 【免费下载链接】logisim-evolution Digital logic design tool and simulator 项目地址: https://gitcode.com/gh_mirrors/lo/logisim-evolution 你是否曾经对计算机内部的奥秘感到好奇&#xff1f…...

基于MCP协议与Gemini大模型构建智能命令行AI助手

1. 项目概述:一个连接命令行与AI的“翻译官” 最近在折腾一些自动化脚本和工具链,发现一个挺有意思的痛点:我手头有一堆用Shell、Python写的命令行工具,它们功能强大,但交互方式仅限于传统的参数和标准输入输出。与此…...

魔兽争霸3游戏优化终极指南:3步解决帧率限制与界面显示问题

魔兽争霸3游戏优化终极指南:3步解决帧率限制与界面显示问题 【免费下载链接】WarcraftHelper Warcraft III Helper , support 1.20e, 1.24e, 1.26a, 1.27a, 1.27b 项目地址: https://gitcode.com/gh_mirrors/wa/WarcraftHelper 还在为魔兽争霸3的卡顿画面和界…...