首页/数据/SQL 速查

SQL 速查

查询语句、连接与子查询、聚合与窗口函数、常用函数、数据变更与事务、执行计划与索引:SQL 语言全场景速查。

共 311 条更新于 2026-10-12所属领域:数据
共 311 条

查询基础

SELECT/WHERE/ORDER/LIMIT 与条件表达式

SELECT 基础查询热门

从表里取数据的基本写法:选择列、指定来源表,再叠加 WHERE / ORDER BY / LIMIT;显式列清单比 SELECT * 更利于稳定输出与减少无关列读取。

WHERE 条件过滤热门

在分组与排序之前过滤行:WHERE 只保留条件为 TRUE 的行;结合 IS NULL、范围与集合条件可以精确圈定数据。

LIMIT 分页与 Top N热门

限定返回行数与偏移:LIMIT n 取前 n 行,OFFSET 跳过若干行;深分页性能差,生产上用键集分页替代大 OFFSET。

IS NULL / IS NOT NULL 判空

NULL 表示“未知”,不能用等号判断;IS [NOT] NULL 是可靠的判空方式,也是计数与条件过滤中常见的坑位。

ORDER BY 排序与稳定性

对结果排序:支持多列、表达式、列序号与别名;没有 ORDER BY 时返回顺序不保证,分页与 Top N 场景必须显式排序。

LIKE 模糊匹配与转义

百分号匹配任意长度、下划线匹配单个字符;前缀模式可走索引,前后都加百分号基本等于全表扫描,必要时用 ESCAPE 处理字面量。

NOT IN 的 NULL 陷阱

NOT IN 对包含 NULL 的集合几乎总是返回空结果:因为 x <> NULL 是 UNKNOWN。识别与改写它是排查“查询莫名没数据”的高频问题。

SELECT 列选择与别名 AS

用别名给输出列和表起短名字:AS 可省略但显式更清楚;别名只影响结果集与部分子句,不改变原表结构。

DISTINCT 去重

对结果集去重:作用于整个 SELECT 列清单,不是单列;统计去重计数用 COUNT(DISTINCT col),注意 NULL 不参与计数。

IN 列表条件

IN 命中一组离散值,等价于若干 OR 但更简洁;列表很长时优化器代价上升,NOT IN 遇到 NULL 是经典陷阱。

CASE 表达式(简单与搜索形式)

SQL 中的条件分支:简单 CASE 做等值匹配,搜索 CASE 书写任意条件;分支自上而下取首个命中,缺 ELSE 时返回 NULL。

SELECT 计算列与表达式

在 SELECT 里直接做算术得到派生列:支持括号、四则运算与取模;注意整数除法与除零行为在 MySQL、PostgreSQL 间不同。

BETWEEN 范围条件

BETWEEN a AND b 等价于 >= a AND <= b,两端都包含;对时间列用日期做边界时要留意时间部分,推荐半开区间写法。

NULL 三值逻辑与运算表现

NULL 参与比较得到 UNKNOWN、参与算术得到 NULL、参与字符串拼接通常也得到 NULL;理解这些规则才能写对过滤与统计。

UNION 与 UNION ALL 合并结果集

纵向拼接两个查询结果:UNION 去重、UNION ALL 保留全部行;能确定无重复时优先 UNION ALL,省去去重开销。

AND / OR / NOT 逻辑组合

组合多个条件时先搞清优先级:NOT 高于 AND、AND 高于 OR;SQL 不保证短路求值,可能报错的表达式不要靠条件顺序保护。

比较运算符与排序规则影响

=、<>、>、< 等比较运算的写法与两个高频细节:字符串比较受排序规则影响(大小写敏感性);与 NULL 比较需要专门语法。

SQL 字面量写法:字符串、数字、日期时间

把常量写进 SQL 的规范写法:字符串用单引号、日期时间用带类型前缀的标准字面量,避免依赖各数据库的松式写法。

SELECT 无来源查询(常量与函数验证)

不指定表也能求值:验证函数、时区、隐式转换行为时很顺手;MySQL 兼容 FROM DUAL,PostgreSQL 不需要 FROM。

别名在 WHERE / HAVING 中的可用性

SELECT 里定义的列别名不能用在 WHERE:逻辑执行顺序中 WHERE 在 SELECT 之前;需要过滤派生列时写原表达式或套子查询。

CASE 自定义排序顺序

按业务枚举顺序排序(如 紧急 > 高 > 普通)的常用写法:把状态映射成数字参与 ORDER BY,避免按拼音或字母排序。

标识符引用:反引号与双引号

表名、列名与保留字冲突时的引用方式:MySQL 用反引号,PostgreSQL 用双引号且区分大小写;跨库 SQL 不要混用。

REGEXP 正则匹配

按正则表达式匹配字符串:MySQL 用 REGEXP/RLIKE 运算符与 REGEXP_* 函数族,PostgreSQL 用 ~ 系列运算符,大小写规则各自不同。

排序中的 NULL 位置处理

NULL 在排序中的位置两库默认不同:MySQL 把 NULL 视为极小值(升序在前),PostgreSQL 视为极大值(升序在后),且只有 PG 支持 NULLS FIRST/LAST。

字符串转义与反斜杠差异

字符串里嵌引号、百分号的处理方式;MySQL 默认把反斜杠当转义符,PostgreSQL 标准字符串中反斜杠是普通字符,迁移前要核对。

布尔表达式与真值类型

PostgreSQL 有原生 boolean 类型,MySQL 用 tinyint(1) 与 0/1 近似;两库在 WHERE 中直接使用布尔表达式的宽严不同。

多列去重与 PostgreSQL DISTINCT ON

多列 DISTINCT 按组合去重;PostgreSQL 的 DISTINCT ON 能实现“每组保留一行”,MySQL 需要用窗口函数改写。

NULL 安全比较:<=> 与 IS DISTINCT FROM

普通等号遇到 NULL 得 UNKNOWN,需要 NULL 安全相等时:MySQL 用 <=>,标准与 PostgreSQL 用 IS [NOT] DISTINCT FROM。

集合运算中的 ORDER BY 与 LIMIT

ORDER BY/LIMIT 写在最后时作用于整个合并结果;要给单个分支排序或限行,必须用括号包住该分支。

INTERSECT 与 EXCEPT 交集/差集

标准集合运算:INTERSECT 取两查询都有的行,EXCEPT 取前一查询有而后一查询没有的行,默认都去重。

SQL 注释:-- 与 /* */

三种注释写法与可执行注释的区别:MySQL 支持 # 单行注释与版本注释 /*! */,PostgreSQL 遵循标准的两类注释。

行构造器比较 (a, b) IN ((…),(…))

把多个列当作一个元组参与 IN 或等值比较,表达“多列组合命中多个候选项”比 OR 链更短更清晰。

查询结果导出:INTO OUTFILE 与 COPY

把 SELECT 结果写到服务器文件:MySQL 用 INTO OUTFILE(受 secure_file_priv 限制),PostgreSQL 用 COPY(服务端)或 psql \copy(客户端)。

连接与子查询

各类 JOIN、子查询与 CTE 写法

LEFT JOIN 左外连接热门

保留左表全部行,右表没有匹配时用 NULL 补齐;适合“主表 + 可选关联信息”的查询。

INNER JOIN 内连接基础热门

按连接条件把两张表的行配对,只保留匹配成功的组合;显式 JOIN 语法比逗号连接更清晰,也不容易漏写连接条件。

ON 与 WHERE 在外连接中的区别

内连接里 ON 与 WHERE 可以互换;外连接中不能:ON 决定配对,WHERE 在配对结果上过滤,写在 WHERE 会滤掉补 NULL 的行。

反连接:找出不存在于另一表的行

反连接三种写法:NOT EXISTS、NOT IN、LEFT JOIN IS NULL;语义与 NULL 行为各不相同,优先 NOT EXISTS。

一对多连接的行数放大

连接“多”侧后结果按多行展开:订单连明细后每个订单出现多行,做统计前先确定口径。

NOT EXISTS 反连接

NOT EXISTS 找“没有对应匹配”的行:与 NULL 无关,是反连接的推荐写法;配合内表索引效率稳定。

CTE:WITH 公共表表达式

用 WITH 给子查询起名字,把多层查询拆成可读的步骤;MySQL 8.0+ 与 PostgreSQL 均支持,作用域限于紧随的语句。

EXISTS 判断存在性

EXISTS 判断子查询是否有行:逻辑上找到首行即返回真,适合“是否存在”类过滤。

递归 CTE:树形结构展开

WITH RECURSIVE 以“初始行 + 递归项”逐步展开层级数据,典型场景是组织架构、分类树、物料清单。

三表及多表连接

多个表依次连接:链式书写、逐步列出条件;每步都可能放大或缩小行数,最终结果粒度要提前想清楚。

每组取最新一行:窗口函数写法

“每个用户最近一笔订单”这类需求的通用解法:ROW_NUMBER 按组内排序编号,取 rn=1 后左连接到主表。

自连接:表连接自身

同一张表连接自身:员工与经理、成对比较等场景;必须用两个不同别名区分两侧,否则无法引用。

左连接后的计数口径

左连接统计时 COUNT(*) 统计连接后的行数(含补 NULL 行),COUNT(右表列) 只统计真正匹配上的行。

连接键为 NULL 的行不会匹配

NULL 与其他任何值(包括 NULL)比较都是 UNKNOWN:连接键含 NULL 的行在内连接中直接消失,在左连接中保留但补 NULL。

IN 子查询与半连接

IN 子查询表达“存在于另一张表”:只要找到匹配就返回该行,不放大行数;优化器通常把它改写为半连接。

派生表:FROM 里的子查询

把子查询当作临时表参与连接或过滤,必须给别名;MySQL 8.0.22 起支持下推条件到派生表,旧版本可能先物化整表。

子查询与 JOIN 的选择

同一需求可以写成 IN/EXISTS 或 JOIN:核心差异在“是否放大行数”与“是否输出另一表列”,性能以执行计划实测为准。

判断存在性:EXISTS 优于 COUNT

只需要判断“有没有”时,EXISTS 找到首行即停;COUNT(*) 要把所有匹配行数完,代价更高。

CROSS JOIN 笛卡尔积

两表无条件配对得到所有组合:常用于生成“尺码 × 颜色”这类组合集,误用时行数按乘积增长。

先聚合再连接

先在子查询里过滤并汇总,得到小结果集再连接主表,通常比连接全部明细再聚合更省资源。

子查询中 ORDER BY 与 LIMIT 的语义

子查询里“排序取前 N 行”只有搭配 LIMIT 才确定;不带 LIMIT 的 ORDER BY 在优化层可能被忽略,不能依赖它。

SELECT 列表里的子查询

在结果列里内嵌标量子查询得到附加信息(计数、最新值):可读性好,但逻辑上逐行执行,行数大时优先改 JOIN 或窗口函数。

LATERAL:子查询引用左侧表

让 FROM 中的子查询引用同一 FROM 里写在它左侧的表(类似逐行相关子查询):PostgreSQL 9.3+、MySQL 8.0.14+ 支持。

相关子查询

子查询引用外层查询的列,逻辑上逐行求值;配合内表索引可高效,否则每行一次扫描。

RIGHT JOIN 右外连接

保留右表全部行,左表无匹配补 NULL;可读性不如把两表交换后用 LEFT JOIN,团队规范里常要求统一成 LEFT JOIN。

标量子查询

用于取值场景的子查询:必须至多返回一行一列;没有匹配行时结果为 NULL。

多个 CTE 与互相引用

一条 WITH 里可以定义多个 CTE(逗号分隔);后定义的可引用先定义的,形成流水线式查询结构,不允许循环引用。

递归 CTE 的深度限制与环检测

数据成环或条件写错时递归不终止:MySQL 有 cte_max_recursion_depth 保护(默认 1000),PostgreSQL 需要自行加深度或路径防护。

CTE 配合 UPDATE / DELETE / INSERT

把筛选逻辑写成 CTE 再驱动数据变更:MySQL 允许 WITH 引导 UPDATE/DELETE;PostgreSQL 还允许在 CTE 内直接执行带 RETURNING 的数据修改。

FULL OUTER JOIN 全外连接

两边都保留、互不匹配的位置补 NULL:PostgreSQL 与标准 SQL 支持 FULL OUTER JOIN,MySQL 不支持,可用 LEFT/RIGHT 加 UNION 模拟。

CTE、派生表与临时表怎么选

单语句内拆解逻辑用 CTE;同一中间结果被多处引用、需要索引或跨语句复用时用临时表。

分表结果合并统计

按时间或业务分表后,用 UNION ALL 合并各分片再聚合;列结构必须一致,聚合放在合并之后。

CTE 物化与内联的选择

CTE 是内联展开还是物化成临时结果会影响性能:PostgreSQL 12 起默认按引用情况决定,MySQL 由优化器自行决定。

展开 JSON 数组为多行(JSON_TABLE 与 LATERAL)

把一行里的 JSON 数组拆成多行参与过滤与统计:MySQL 8 用 JSON_TABLE,PostgreSQL 用 jsonb_array_elements 配合 LATERAL。

USING 与 NATURAL JOIN

两表同名列可用 USING(col) 简化连接条件,结果中该列只出现一次;NATURAL JOIN 按所有同名列自动连接,隐式且风险高。

递归 CTE 生成数字与日期序列

用递归生成连续整数或日期,补全报表空缺天数;PostgreSQL 另有 generate_series,写法更短。

ANY / ALL 子查询比较

比较运算符配合 ANY/SOME/ALL 表达“与任意一个比较 / 与所有值比较”:= ANY 等价 IN,<> ALL 等价 NOT IN,NULL 规则相同。

非等值连接:范围与不等条件

连接条件可以用任何布尔表达式:价格落在区间、时间重叠等场景用范围连接,注意区间重叠会导致一行命中多条规则。

复合键连接

多列共同构成连接键时,ON 中逐列相等;漏写某一列会放宽条件导致错配或行数翻倍,复合索引也要按列序匹配。

强制连接顺序:STRAIGHT_JOIN 与提示

MySQL 可用 STRAIGHT_JOIN 强制按书写顺序连接,用于优化器偶发选错顺序的场景;PostgreSQL 一般通过统计信息与规划参数间接影响。

聚合与窗口函数

分组统计、排名与累计计算

GROUP BY 分组统计热门

按列值分组后对每组计算聚合:SELECT 列表里只能出现分组列与聚合表达式,这是标准与两库默认强制的约束。

COUNT 计数热门

统计行数或非空值个数:COUNT(*) 统计行数,COUNT(col) 只统计该列非 NULL 的值;无匹配行时返回 0。

窗口函数概念与语法

窗口函数在保留明细行的同时做组内计算:函数 OVER (PARTITION BY … ORDER BY … [帧]);MySQL 8.0+ 与 PostgreSQL 均支持。

HAVING 过滤分组结果

HAVING 在分组与聚合之后过滤:条件里可以用聚合函数,HAVING COUNT(*) > 5 是典型用法。

ROW_NUMBER 组内行号

为分区内的行按排序生成连续唯一编号(1,2,3…),用于分组取前 N 行、去重取最新等场景。

COUNT(DISTINCT) 去重计数

统计去重后的个数,例如独立用户数;NULL 不参与计数,MySQL 还支持多列组合去重。

SUM 求和

对数值列求和,忽略 NULL;没有任何行或全为 NULL 时返回 NULL,报表场景常用 COALESCE 兜底。

WHERE 与 HAVING 的分工

WHERE 过滤行、HAVING 过滤组:同一条件写在哪一层会影响参与分组的数据量与结果正确性。

累计求和(running total)

用 SUM(...) OVER (ORDER BY …) 计算截至当前行的累计值:销售额累计、账户流水余额等经典场景。

COUNT(*) 与 COUNT(col) 的区别

两者都可能出现在同一条 SQL 里但含义不同:COUNT(*) 数行;COUNT(col) 数非 NULL 值。排查数据质量时常用两者差值找空值。

按天/月聚合统计

时间维度的报表基础:把时间戳截断到天或月再分组;注意索引友好写法与跨天边界口径。

每组取前 N 行

分组 Top N 的标准解法:ROW_NUMBER(严格 N 行)或 RANK(含并列)编号后在外层过滤,窗口函数不能直接写进 WHERE。

按表达式或函数分组

分组键可以是表达式:按天/月统计是常见需求;表达式分组通常无法直接用普通索引,可考虑生成列或预聚合。

条件聚合(多种口径一次算出)

用 CASE/布尔表达式在聚合内部区分条件,一条 SQL 同时算出多个指标,避免多次扫描同一张表。

LAG 取上一行值

取当前行之前第 N 行的值:环比、差值、会话切分等时序计算的基础;首行没有前值时返回默认值(可指定)。

窗口函数去重:每组只留一行

去重取最新/最早一条的通用写法:PARTITION BY 去重键 + ORDER BY 排序 + rn=1;比 GROUP BY 更容易保留整行信息。

AVG 平均值与口径

平均值 = 非 NULL 值之和 ÷ 非 NULL 值个数;与 SUM/COUNT(*) 的口径不同,报表口径要先定义清楚。

多列分组

GROUP BY 多列时按列组合分组:结果行数等于组合数;顺序影响中间排序但结果集一致。

GROUP_CONCAT 分组拼接(MySQL)

把组内值拼成一个字符串:支持 DISTINCT、排序与自定义分隔符;默认长度上限 1024 字节,超出会静默截断。

RANK 排名(并列跳号)

按排序值排名:并列名次相同,后续名次跳号(1,1,3…);取“前 N 名含并列”用 RANK 而不是 ROW_NUMBER。

窗口函数与 GROUP BY 的选择

需要保留明细行、做组内对比时用窗口函数;只需要每组的汇总值时用 GROUP BY 更直接。

ONLY_FULL_GROUP_BY 与分组合法性

非聚合列不在 GROUP BY 中时:MySQL 默认模式直接报错(ONLY_FULL_GROUP_BY),PostgreSQL 同样拒绝;识别主键函数依赖可放行。

聚合函数与 NULL 的关系

SUM/AVG/MAX/MIN 忽略 NULL 输入;无输入时返回 NULL;COUNT 家族的行为不同(COUNT(*) 为 0)。写报表时这组规则必须分清。

占比与比率计算

比率 = 部分 / 整体:用聚合相除并防止整数除法与除零;MySQL 与 PostgreSQL 的整数除法行为不同。

环比计算(与上期对比)

用 LAG 取上一期值算环比:注意分区(门店/品类)与排序(月份)要写全,否则跨对象对比会出错。

MIN / MAX 最值统计

取列的极小值与极大值;忽略 NULL,可用于时间范围、价格区间等场景,配合 GROUP BY 得到分组极值。

用 SUM(CASE) 做行转列透视

不依赖专用函数实现行列转换:把要展开的维度值写成 CASE 分支,外层 SUM/COUNT 得到透视表;维度值需提前确定。

移动平均

用窗口帧计算近 N 行均值(如近 7 天平均销量),平滑波动;帧写法 ROWS BETWEEN 6 PRECEDING AND CURRENT ROW。

占比计算(组内份额)

当前行值 ÷ 组内总和:用 SUM(...) OVER (PARTITION BY ...) 得到分母,一次扫描算出份额。

组内计数广播 COUNT(*) OVER

不改行数地给每行附上组内统计(组大小、组内极值),常用于占比、排名并列判断与数据探查。

ROLLUP 分组小计与合计

GROUP BY ... WITH ROLLUP 在结果中追加小计与总计行:MySQL 8 与 PostgreSQL 均支持,小计行的分组列显示为 NULL。

LAST_VALUE 与默认帧的坑

LAST_VALUE 默认帧是“分区起点到当前行”,直接写会得到当前行值;要取分区最后一行必须显式扩展帧到分区结尾。

窗口函数的使用限制

窗口函数只能出现在 SELECT 列表与 ORDER BY 中:WHERE、GROUP BY、HAVING 里不能用;要筛选计算结果必须套子查询。

DENSE_RANK 排名(并列不跳号)

并列名次相同且后续不跳号(1,1,2,3…):适合“等级档位”类排名展示。

LEAD 取下一行值

取当前行之后第 N 行的值:计算截止时间、下次登录间隔、流程步骤耗时等场景。

JSON 聚合:JSON_ARRAYAGG 与 json_agg

把组内数据聚合成 JSON 数组/对象,接口直接消费;MySQL 8 用 JSON_ARRAYAGG/JSON_OBJECTAGG,PostgreSQL 用 json_agg/jsonb_object_agg。

大表计数:精确与近似

InnoDB 的 COUNT(*) 需要扫描;报表里动辄全表计数时,可用统计信息近似值或计数表方案。

ROWS 与 RANGE 帧的区别

窗口帧决定函数看哪些行:ROWS 按物理行数,RANGE 按排序值的区间(并列值会一起进来);省略时默认 RANGE。

同比计算(跨 12 期)

LAG(x, 12) 取去年同月值算同比;前提是数据按月连续、每年 12 期,写死偏移量时先校验数据完整性。

带 FILTER 的聚合(PostgreSQL)

PostgreSQL 支持聚合函数加 FILTER (WHERE …),只对满足条件的输入计算;MySQL 需要用 CASE 表达式达到同样效果。

FIRST_VALUE 组内首值

取窗口帧内首行的值:把“组内最早/排在首位”的字段广播到每一行,用于对比与填充。

窗口函数的默认帧

有 ORDER BY 时默认帧是 RANGE UNBOUNDED PRECEDING AND CURRENT ROW;没有 ORDER BY 时是整个分区。这解释了很多“结果和想象不一样”。

HAVING 中使用别名(方言差异)

MySQL 允许在 HAVING 引用 SELECT 别名;PostgreSQL 不支持,需要重复写聚合表达式或套一层子查询。

string_agg 字符串聚合(PostgreSQL)

PostgreSQL 的字符串聚合函数:string_agg(值, 分隔符 [ORDER BY …]);MySQL 对应 GROUP_CONCAT。

DISTINCT 与 GROUP BY 去重的等价关系

SELECT DISTINCT a, b 与 SELECT a, b ... GROUP BY a, b 在结果层等价;需要附加聚合时用 GROUP BY 更自然。

NTILE 分桶

把分区内行按顺序尽量均匀分成 n 桶(1..n),用于分位、TOP 比例抽样等场景。

GROUPING() 区分小计行

GROUPING(列) 在超级聚合(小计/合计)行返回 1、普通行返回 0,用来把 NULL 与小计正确区分开。

WINDOW 子句命名窗口

多个窗口函数复用同一 OVER 定义时,用 WINDOW 子句命名,减少重复与笔误;MySQL 8 与 PostgreSQL 都支持。

中位数与百分位(percentile_cont)

中位数/百分位用分位函数计算:PostgreSQL 用 percentile_cont/percentile_disc;MySQL 8 没有内置等价函数,需要用窗口函数近似或应用层计算。

PERCENT_RANK 相对排名

相对排名 = (名次 - 1) / (总行数 - 1),取值 0 到 1;用于“排在前面百分之多少”。

GROUPING SETS 与 CUBE(PostgreSQL)

一条查询同时产出多种分组口径:PostgreSQL 支持 GROUPING SETS 与 CUBE;MySQL 8 只有 ROLLUP。

GROUP BY 列序号

MySQL 与 PostgreSQL 都允许 GROUP BY 1 这类列序号写法:简短但可读性差,改 SELECT 顺序时容易改错。

NTH_VALUE 取第 N 行值

取窗口帧内第 N 行的值:例如组内第二早的订单时间;N 超出帧范围时返回 NULL。

CUME_DIST 累积分布

返回“小于等于当前排序值的行数占分区比例”,取值 (0,1];与 PERCENT_RANK 的区别在于并列值的处理。

函数速查

字符串、日期时间、数值与 JSON 函数

CONCAT 字符串拼接热门

拼接多个字符串:MySQL 的 CONCAT 遇到 NULL 会让整行结果变 NULL,带分隔符拼接用 CONCAT_WS 会跳过 NULL 项。

COALESCE 取首个非 NULL 值

按顺序返回首个非 NULL 的参数:做默认值、多字段兜底、把 NULL 转成业务默认值时使用,是 SQL 标准函数。

NOW / CURRENT_TIMESTAMP 当前时间

取当前日期时间:MySQL NOW() 在语句执行时取值;PostgreSQL now() 等于事务开始时间,同一事务内多次调用结果相同。

DATE_ADD / INTERVAL 日期加减

日期加减的主力语法:MySQL 用 DATE_ADD(d, INTERVAL n UNIT) 或 d ± INTERVAL;PostgreSQL 用 d ± interval 'n unit'。

SUBSTRING 截取子串

按位置截取子串:MySQL 支持负数位置从尾部数;PostgreSQL 用 substring(str from start for len),位置从 1 开始。

LIKE 通配符与 ESCAPE 转义

LIKE 里 % 与 _ 是通配符:搜索字面量 % / _ 必须转义;用 ESCAPE 子句显式指定转义符比依赖反斜杠更清晰。

DATE_FORMAT 与 to_char 格式化

把日期时间格式化为字符串:MySQL 用 % 占位符,PostgreSQL 用 to_char 模板;两者模板字母含义不同,迁移时逐项核对。

date_trunc 时间截断(PostgreSQL)与 MySQL 等价写法

把时间截断到指定粒度(月/周/日/小时),做时间分桶统计的核心工具:PostgreSQL 有 date_trunc,MySQL 需要用日期运算拼装。

DECIMAL 精度与浮点误区

精确小数用 DECIMAL/NUMERIC:金额、数量、税率一律用定点类型;FLOAT/DOUBLE 是近似值,二进制表示会带来比较与累计误差。

JSON_EXTRACT 提取 JSON 值

从 JSON 文档里按键或下标取值:MySQL 有 JSON_EXTRACT 函数与 -> / ->> 运算符;PostgreSQL 用 jsonb 运算符或 jsonpath。

TRIM / LTRIM / RTRIM 去空白

去掉字符串两端的空白或指定字符:TRIM 默认只去半角空格,清洗用户输入时通常还要处理制表符与不换行空格。

REGEXP_REPLACE 正则替换

用正则做替换:批量清洗手机号、脱敏、格式规整;两库的默认替换次数与捕获组写法不同,跨库改写要逐条核对。

UUID 生成与存储

生成全局唯一标识:MySQL UUID() 返回 UUID v1 字符串;PostgreSQL 用 gen_random_uuid() 返回原生 uuid 类型。

EXTRACT 提取日期字段

从日期时间中取出年/月/日/时/分/周等字段:标准写法 EXTRACT(unit FROM expr),MySQL 另有 YEAR()/MONTH() 等简写。

UNIX_TIMESTAMP 与 FROM_UNIXTIME

Unix 时间戳与日期时间互转:MySQL 提供专用函数;PostgreSQL 用 extract(epoch) 与 to_timestamp,注意秒/毫秒与显示时区。

日期范围查询的边界写法

按时间过滤推荐半开区间 [起点, 次日):用 < 下月 1 日 而不是 BETWEEN ... 月末 23:59:59,避免漏掉毫秒数据。

CAST / CONVERT 类型转换

显式类型转换:MySQL 用 CAST(x AS SIGNED/UNSIGNED/CHAR/DECIMAL...),PostgreSQL 用 CAST(x AS type) 或 x::type;非法文本的处理策略不同。

-> 与 ->> 的区别与比较场景

JSON 取值的两个运算符:-> 返回 JSON 类型(字符串带引号、可用于后续 JSON 函数),->> 返回文本(用于比较与展示)。

LENGTH 与 CHAR_LENGTH 长度函数

计算字符串长度:MySQL 的 LENGTH 按字节、CHAR_LENGTH 按字符;PostgreSQL 的 length 按字符、octet_length 按字节,统计中文时容易踩坑。

哈希函数:MD5 / SHA2 / CRC32

计算摘要用于校验与去重:MySQL 提供 MD5/SHA1/SHA2/CRC32;PostgreSQL 内置 md5 与 sha 系列,更多算法用 pgcrypto 的 digest()。

NULLIF 等值转空

当两个参数相等时返回 NULL,否则返回首个参数:保护除法、把哨兵值(如 0、'N/A')转成 NULL 的标准做法。

TIMESTAMPDIFF 时间间隔计算

按指定单位计算两个时间点的差值(单位边界数):MySQL 直接支持;PostgreSQL 用时间戳相减取 epoch 换算。

CEIL / FLOOR 向上向下取整

向正负方向取整:CEIL 向上(天花板)、FLOOR 向下(地板);分页总页数、资源规格向上取整等场景常用。

JSON_SET / JSON_INSERT / JSON_REPLACE 与 jsonb_set

修改 JSON 文档内字段:MySQL 三兄弟分工是“插或改 / 只插 / 只改”;PostgreSQL 用 jsonb_set 与删除运算符。

LEFT / RIGHT 取左右子串

从字符串左端或右端取固定长度:常用于取编号前缀、手机号后四位、年份前两位;按字符计算,适合处理多字节文本。

REPLACE 字符串替换

把出现的所有子串替换为新内容:字面量替换、区分大小写、不支持正则;批量脱敏、清理固定后缀时高频使用。

STR_TO_DATE 字符串转日期

把字符串按格式解析为日期/时间值:导入外部数据、清洗脏日期列时使用;解析失败 MySQL 返回 NULL 并告警,PostgreSQL 直接报错。

时间戳与时区:CONVERT_TZ 与 AT TIME ZONE

跨时区存取的两种主流做法:MySQL 用 CONVERT_TZ 显式换算(依赖时区表);PostgreSQL 用 AT TIME ZONE 配合 timestamptz。

ROUND 四舍五入与精度陷阱

按小数位舍入:整数位也可通过负的位数处理;浮点参数的舍入行为与十进制精度有关,金额场景应使用 DECIMAL。

整数除法与除法精度

除法结果类型是跨库高频差异点:MySQL 的 / 得小数、DIV 取整数;PostgreSQL 整数相除直接截断,需要显式转 numeric。

JSON_CONTAINS 与 jsonb 包含查询

判断 JSON 里是否包含某个值或结构:MySQL 用 JSON_CONTAINS/JSON_CONTAINS_PATH,PostgreSQL 用 jsonb 的 @> 与存在运算符。

LOCATE / INSTR / POSITION 子串定位

返回子串首次出现的位置(找不到返回 0 或 NULL 视函数而定):三个函数参数顺序不同,是常见的抄错点。

SUBSTRING_INDEX 与 split_part 按分隔符切分

按分隔符取第 N 段或某段之前/之后的内容:解析路径、IP、版本号、逗号串时很实用。

DATEDIFF 天数差

计算两个日期相差的天数:MySQL DATEDIFF(a,b)=a-b(只取日期部分);PostgreSQL 用 date - date 直接得整数,时间戳相减得 interval。

DAYOFWEEK / WEEKDAY 与 DOW 星期计算

取星期序号做工作日/周末判断:三套编号(MySQL DAYOFWEEK 周日=1、WEEKDAY 周一=0、PG DOW 周日=0)混用是经典 bug 来源。

GREATEST / LEAST 多值比较(NULL 规则不同)

在一组值里取较大者/较小者:多条候选取优场景常用;两库对 NULL 的处理完全相反,是迁移时的隐藏雷区。

JSON_OBJECT / JSON_ARRAY 构造 JSON

在 SQL 里构造 JSON 对象与数组:接口返回、宽表导出、事件打点时拼 JSON 结构。

PostgreSQL JSON 与 JSONB 选型

两种 JSON 类型的取舍:jsonb 是解析后的二进制格式,支持索引与高效包含查询;json 原样保存文本,只适合“原样还原”场景。

LPAD / RPAD 补位与截断

按指定长度左右补位(常用于编号前补零),长度小于原串时会从另一端截断;补位串可以多于 1 个字符。

UPPER / LOWER 大小写转换

转大写或小写:跨库迁移时要注意比较行为差异——MySQL 默认排序规则不区分大小写,PostgreSQL 默认区分。

REGEXP_SUBSTR 与 regexp_match 提取匹配片段

从文本中抽出符合模式的片段:解析日志行、提取 URL 参数、抓取编号;比 SUBSTRING 固定位置灵活得多。

CURDATE / CURTIME 取日期或时间部分

只取当前日期或当前时间:MySQL 用 CURDATE()/CURTIME();PostgreSQL 用 CURRENT_DATE / LOCALTIME,注意日期加减写法的差异。

INTERVAL 运算的月底与语义细节

INTERVAL 的日期运算有隐含规则:加月遇到目标月天数不足会截到月末;'1 month' 与 '30 days' 并不等价。

MOD 取模与分桶

取余数:分表路由、采样、奇偶判断常用;对负数取模的符号规则与除零行为两库不同,分桶公式要写防御性版本。

JSON 路径语法与 jsonpath

路径表达式写法:MySQL 用 '$' 开头的路径字符串;PostgreSQL 运算符用键/数组路径,PG 12+ 的 jsonpath 与 MySQL 风格接近。

JSON_TABLE 展开 JSON 数组(MySQL 8)

把 JSON 数组转成关系行:MySQL 的 JSON_TABLE 可在 FROM 中直接展开,便于与普通表连接和聚合。

CONVERT USING 与 convert_from 字符集转换

字符集转换与检测:MySQL 有 CONVERT(expr USING cs) 与 CHARSET()/COLLATION();PostgreSQL 用 convert_to/convert_from 处理字节与文本互转。

IFNULL 与 ISNULL(MySQL)

MySQL 专用:IFNULL(a,b) 两参兜底;ISNULL(x) 是函数形式判断空值。PostgreSQL 没有 IFNULL,统一写 COALESCE。

WEEK / YEARWEEK 周编号与 mode 参数

按周分组统计时的口径控制:MySQL 的 WEEK/YEARWEEK 有 mode 参数决定周起始与计算方式,PostgreSQL 固定 ISO 周。

POW / SQRT / LOG 幂与对数

幂、开方与对数:容量估算、增长率、评分加权会用到;注意两库 LOG 的默认底数不同。

RAND / random 随机数与采样

生成随机数:随机抽样、造测试数据、加盐场景常用;对超大表 ORDER BY RAND() 代价很高,PG 可用 TABLESAMPLE。

JSON_VALID 与 JSON_TYPE / jsonb_typeof

校验与识别 JSON 结构:把文本转换/入列前先验证,排查线上数据时看清每个节点的类型。

jsonb_array_elements 展开数组(PostgreSQL)

PostgreSQL 把 JSON 数组展开成多行的惯用函数族:可带文本版本与序号,是处理 JSON 明细的基础操作。

LAST_DAY 取月末日期

返回所在月份的最后一天:做月度对账、账单周期、月末快照时常用;MySQL 有 LAST_DAY,PostgreSQL 用月初加一个月再减一天。

JSON_MERGE_PATCH / MERGE_PRESERVE 与 || 合并

合并两个 JSON 文档:MySQL 提供 patch(RFC 7396 风格)与 preserve 两种;PostgreSQL 用 || 做“右值覆盖”式浅合并。

IF() 条件函数(MySQL)与跨库写法

MySQL 的 IF(cond, a, b) 是函数式三元表达式,能直接写在 SELECT 里;PostgreSQL 没有该表达式,统一用 CASE WHEN。

ABS / SIGN 绝对值与符号

取绝对值与判断正负:误差比较、金额方向、变动幅度计算的基础函数;SIGN 返回 -1、0、1。

REPEAT / REVERSE 重复与反转

重复字符串与反转字符串:造分隔线、生成占位、验证回文与编码问题时会用到。

数字格式化:FORMAT 与 to_char

给数字加千分位与小数位展示:MySQL 用 FORMAT(),PostgreSQL 用 to_char();输出都是字符串,仅用于展示层。

TRUNCATE 截断小数(注意与清表语句同名)

按位数直接截断、不做舍入:MySQL TRUNCATE(x,d)、PostgreSQL trunc(x,d);名字与 TRUNCATE TABLE 相同但不是一回事。

变更与事务

增删改、事务控制与隔离级别

UPDATE 基础与安全边界热门

更新满足条件的行:SET 支持多列赋值与表达式;漏写 WHERE 会更新全表,是生产事故的高频来源。

INSERT VALUES 插入数据

按列清单逐行或多行插入:显式列出列名可读且抗表结构变更;多行 VALUES 明显减少网络往返。

事务基础:BEGIN / COMMIT / ROLLBACK

把多条语句打包成原子操作:MySQL 用 START TRANSACTION 或 BEGIN,PostgreSQL 用 BEGIN;提交用 COMMIT,撤销用 ROLLBACK。

Upsert:ON DUPLICATE KEY UPDATE 与 ON CONFLICT

“存在则更新、不存在则插入”:MySQL 用 ON DUPLICATE KEY UPDATE,PostgreSQL 用 ON CONFLICT,是幂等写入的基础写法。

DELETE 基础与分批删除

按条件删除行:逐行记录日志、可回滚、触发 DELETE 触发器;大表删除要分批做,避免长事务与主从延迟。

CREATE TABLE 建表要点

建表时把主键、约束、字符集、引擎一次定清楚:MySQL 常用 InnoDB + utf8mb4;PostgreSQL 关注类型与约束表达。

事务隔离级别与设置方法

四档隔离级别控制并发读写行为:MySQL 默认 REPEATABLE READ,PostgreSQL 默认 READ COMMITTED;改级别可按会话或按事务。

锁读:SELECT FOR UPDATE / FOR SHARE

在事务里对行加锁再读写:解决“先查后改”的并发竞争;MySQL 与 PostgreSQL 语法接近,锁强度不同。

死锁的原理与应对

两个事务互相持有对方需要的锁形成环路:InnoDB 与 PostgreSQL 都会自动检测并回滚其中一个事务,应用侧必须能重试。

INSERT ... SELECT 拷数据

把查询结果直接写入目标表:数据搬迁、归档、宽表预计算的主力写法;不需要 VALUES 关键字。

LAST_INSERT_ID 与自增主键回填

取刚插入行的自增主键:MySQL 的 LAST_INSERT_ID() 是连接级值,不随其它连接变化;PostgreSQL 用 RETURNING 或 currval。

跨表更新:UPDATE ... FROM 与 UPDATE JOIN

用另一张表的数据更新本表:PostgreSQL 用 UPDATE ... FROM,MySQL 用 UPDATE ... JOIN;注意一对多匹配的不确定性。

ALTER TABLE 的锁与执行方式

结构变更的锁代价差异很大:MySQL 支持 INSTANT/INPLACE 减少锁表,PostgreSQL 多数操作会持有 ACCESS EXCLUSIVE。

RETURNING 返回插入结果(PostgreSQL)

插入/更新/删除后直接返回受影响的行数据:PostgreSQL 全支持;MySQL 没有 RETURNING,只能取自增 ID。

DELETE / TRUNCATE / DROP TABLE 对比

三种“删数据”的语义与代价差异明显:选错轻则慢,重则不可回滚丢结构。

autocommit 行为差异

MySQL 默认 autocommit=1(每条语句自动提交);PostgreSQL 没有该开关,天然“每条语句一个隐式事务”,除非显式 BEGIN。

长事务与悬挂事务的危害

长时间不提交的事务会拖住清理与统计:InnoDB 的 purge、PostgreSQL 的 vacuum 都被迫保留旧版本,还可能与 DDL 相互阻塞。

批量导入:LOAD DATA 与 COPY

从文件批量装载数据:MySQL 用 LOAD DATA INFILE(服务端/客户端本地),PostgreSQL 用 COPY(服务端)或 \copy(客户端)。

级联删除与外键动作

外键的 ON DELETE 动作决定父行删除时子行的命运:CASCADE 连带删除、SET NULL 置空、RESTRICT/NO ACTION 阻止删除。

隐式提交:DDL 与事务的边界

MySQL 里 DDL 语句会隐式提交当前事务;PostgreSQL 的 DDL 是事务性的、可以回滚,但持有更强的锁。

MVCC 与快照读:为什么两次查询结果不同

多版本并发控制让读不阻塞写:PostgreSQL 每个语句取快照(READ COMMITTED)、REPEATABLE READ 取事务快照;InnoDB 通过 undo 构造一致性读视图。

NOWAIT / SKIP LOCKED 锁读策略

锁读的两个变体:NOWAIT 拿不到锁立刻报错,SKIP LOCKED 跳过被锁行——后者是队列消费场景的常用模式。

排查锁等待:谁在阻塞谁

线上出现锁等待时先找出持锁会话与等待链:MySQL 用 performance_schema.data_lock_waits,PostgreSQL 用 pg_locks 与 pg_blocking_pids。

MERGE 语句(PostgreSQL 15+)

标准化的“合并”语句:按条件匹配则更新、不匹配则插入(还可 WHEN NOT MATCHED BY SOURCE 时删除);PostgreSQL 15 起支持,MySQL 无此语句。

MySQL 报错 1093:更新时查询同表

MySQL 不允许在 UPDATE/DELETE 的子查询里直接读同一张表;用派生表包一层或改 JOIN 绕开,是高频报错。

TRUNCATE TABLE 清空表的边界

快速清空全表:MySQL 里是 DDL(隐式提交、不可回滚),PostgreSQL 里可回滚但持有 ACCESS EXCLUSIVE 锁。

并发异常:脏读、不可重复读、幻读

三类典型并发异常与隔离级别的对应关系:级别越高异常越少,但冲突与重试成本上升。

锁等待与超时参数

控制等锁的耐心:MySQL 有 innodb_lock_wait_timeout;PostgreSQL 默认无限等待,需要显式设置 lock_timeout / statement_timeout。

CREATE INDEX 基础写法

建索引的常规语法与命名:单列、复合列顺序、唯一索引与删除索引;大表操作前先查看现有索引避免重复。

INSERT IGNORE 与 ON CONFLICT DO NOTHING

跳过冲突行的插入:MySQL 用 INSERT IGNORE,PostgreSQL 用 ON CONFLICT DO NOTHING;前者还会把其它错误降级为警告。

分批更新:UPDATE ORDER BY LIMIT 与 ctid 方案

大表更新采用分批提交:MySQL 支持 UPDATE ... ORDER BY ... LIMIT;PostgreSQL 没有 LIMIT,用 ctid/主键子查询分包。

删除关联数据:多表 DELETE 与 USING

按另一张表的条件删除:MySQL 用多表 DELETE ... FROM t1 JOIN t2,PostgreSQL 用 DELETE ... USING。

SAVEPOINT 部分回滚

事务内设置保存点,出错时只回滚到某个点而不是整个事务:批量处理中“跳过坏行、保留好行”的常用手段。

乐观锁:版本号条件更新

不提前加锁,用版本号在 UPDATE 时校验:更新影响行数为 0 说明发生并发修改,业务层决定重试或报冲突。

默认值、显式 NULL 与 DEFAULT 关键字

省略列取默认值,显式 NULL 存空值:两者语义不同;需要强制取默认值时用 DEFAULT 关键字。

PostgreSQL 分批删除写法与膨胀控制

PostgreSQL 没有 DELETE LIMIT:用 ctid 子查询分批;删除只是标记死元组,空间回收依赖 VACUUM,批量删除要配合清理策略。

SERIALIZABLE 的两种实现:SSI 与锁

同为 SERIALIZABLE:PostgreSQL 用 SSI(乐观检测、冲突中止),MySQL InnoDB 把普通读升级为共享锁(悲观、等待增多)。

加列:位置控制与成本差异

加列的写法与成本:MySQL 支持 FIRST/AFTER 指定位置;PostgreSQL 只能加在末尾(列顺序不可变)。

改列定义与改类型

修改列的类型/可空性/默认值:MySQL 用 MODIFY(可同时改名用 CHANGE),PostgreSQL 用 ALTER COLUMN 分动作执行。

REPLACE INTO 的真实语义(删除再插入)

MySQL 的 REPLACE 不是 UPDATE:遇到唯一键冲突先 DELETE 旧行再 INSERT 新行,未给出的列会重置为默认值。

间隙锁(Gap Lock)与幻读抑制

InnoDB 在 REPEATABLE READ 下用 next-key 锁(记录锁+间隙锁)锁住范围,防住别的事务在区间内插入;PostgreSQL 没有间隙锁。

并发失败重试模式

对死锁与序列化失败的标准处理:捕获特定错误、回滚、短暂退避后重试;重试需要幂等设计配合。

DROP TABLE 前的安全检查

删表不可逆:执行前确认外键引用、依赖对象与备份;PostgreSQL 的 CASCADE 会连视图一起删,MySQL 遇外键引用会拒绝。

受影响行数:changed 与 matched 的区别

确认 DML 实际影响:MySQL 默认返回“发生变化”的行数,开启 CLIENT_FOUND_ROWS 后返回“匹配到”的行数;PostgreSQL 返回处理行数。

RENAME TABLE 改名与影响面

表改名很快,但依赖它的对象与代码要同步:MySQL 用 RENAME TABLE(可一条语句多表原子换名),PostgreSQL 用 ALTER TABLE ... RENAME TO。

DROP INDEX 前的依赖检查

索引可能承担唯一约束或支撑外键:删除前确认约束依赖与使用情况,避免删出约束失效或外键报错。

外键创建与级联选项

用外键表达引用完整性:ON DELETE/UPDATE 决定父行变化时子行行为;外键列要建索引,写入路径也要评估锁影响。

CHECK 约束

用表达式限制列值范围:MySQL 8.0.16 起真正强制执行,PostgreSQL 长期支持;违反时写入直接报错。

只读事务的用途与写法

声明只读事务:给数据库优化空间、避免误写,适合报表、备份、批量导出连接。

生成列(虚拟与存储)

由其他列计算得出:虚拟列即时计算不占存储,存储列落盘、可建索引;常用于把表达式固化成列。

临时表的使用与边界

会话级表:适合拆分复杂批处理与中间结果;会话结束自动清理,注意连接池复用与事务语义差异。

CREATE VIEW 基础与物化视图

把常用查询固化为视图:简化访问与权限控制;注意普通视图不存数据,PG 需要物化视图才可落盘加速。

性能与执行计划

EXPLAIN 解读、索引策略与慢查询分析

EXPLAIN 查看执行计划

不真正执行语句就返回优化器选择的访问路径:每张表怎么访问、用哪个索引、预估多少行,是排查慢查询的常用起点。

EXPLAIN 关键列总览

id、type、key、key_len、rows、filtered、Extra 各列分别回答什么问题:理解列含义才能把输出读成有效信息。

PostgreSQL EXPLAIN 基础与 cost 解读

PG 的 EXPLAIN 输出计划树与启动/总成本估算:cost 是统计模型下的抽象单位,用于比较不同计划而非预测耗时。

EXPLAIN type 访问类型解读

从 const、eq_ref、ref、range 到 ALL:type 列描述每张表的访问方式,注意 index 与 ALL 都可能是整树/整表扫描。

联合索引的前缀使用规则

复合索引 (a,b,c) 只有从 a 开始连续使用才能有效:跳过前导列、或在中间列用范围,都会截断后续列的索引查找。

EXPLAIN Extra 常见标记解读

Using index、Using where、Using index condition、Using filesort、Using temporary:Extra 说明过滤与排序发生在哪一层。

B 树索引适用与不适用场景

B 树索引支持等值、范围、前缀匹配与排序;对列上做运算、前置通配、类型不匹配的条件帮不上忙。

EXPLAIN ANALYZE 实测统计

MySQL 8.0.18+ 会真正执行语句,输出每个节点的估算与实际 rows、耗时对比,用于发现估算偏差。

PG EXPLAIN ANALYZE 与 BUFFERS

ANALYZE 真正执行查询并给出实际行数、耗时与循环次数;BUFFERS 附加共享缓存命中与磁盘读取统计。

覆盖索引避免回表

查询需要的列都在索引中时,引擎可直接从索引返回结果(Extra 显示 Using index);InnoDB 二级索引天然包含主键列。

慢查询日志开启与查看

把执行时间超过 long_query_time 的语句记入日志文件:定位慢 SQL 的常规入口,可加开关同时记录未使用索引的语句。

列上做运算导致索引失效

WHERE 里对索引列做函数或运算时,B 树无法定位范围:改写成对常量做运算,或使用函数索引。

EXPLAIN FORMAT=TREE 与 FORMAT=JSON

TREE 把计划渲染成树形并带估算成本(8.0.16+),JSON 提供机器可读的成本明细,两者都可用于对比不同写法。

pg_stat_statements 找重查询

按语句模板累计调用次数与执行时间:PG 上做查询负载分析的基础扩展,需要预加载后启用。

ORDER BY 走索引消除排序

排序结果与索引顺序一致时可直接按序读索引:关注 EXPLAIN 是否出现排序步骤与回表代价。

隐式类型转换让索引失效

字符串列与数字比较时,列被隐式转为数字:索引无法使用;把字面量改成与列同类型即可。

key_len 判断复合索引用了几列

key_len 是索引查找实际用到的字节数:对照列定义宽度可以推断复合索引命中前几列,验证前缀使用情况。

performance_schema 按摘要找重查询

events_statements_summary_by_digest 按语句模板聚合调用次数与耗时:不用翻日志就能找出实例里的主要负载。

PG 扫描节点:Seq / Index / Bitmap

Seq Scan、Index Scan、Index Only Scan、Bitmap Heap Scan 各有适用面:识别计划树中的扫描方式判断瓶颈环节。

ANALYZE 更新统计信息

优化器依赖统计信息估算行数:数据大改动后计划变差,先 ANALYZE 再谈改写与加索引。

深分页优化:keyset 分页

OFFSET 很大时数据库仍要逐行跳过:改用“上一页最后一条的键”做条件,让每页都走索引定位。

rows 与 filtered 估算解读

rows 是预估扫描行数、filtered 是过滤后剩余百分比:两者相乘得到传给下一步的行数估算,用来定位低效过滤点。

sys schema 巡检视图

sys 把 performance_schema 原始数据整理成可读结果:全表扫描语句、表级 IO、未使用索引都有对应视图。

PG 连接节点:Nested Loop / Hash / Merge

计划树里三种连接算法各有适用场景:驱动集大小、内表索引、两侧有序性是选择依据。

索引条件下推 ICP

MySQL 5.6+ 把部分 WHERE 条件下推到存储引擎、在索引层先过滤(Extra: Using index condition),减少回表次数。

连接驱动顺序与索引配对

连接把“过滤后结果小”的一侧做驱动、另一侧连接列建索引:这是带来数量级差异的结构性因素。

批量写入调优要点

多行 INSERT、批提交事务、批量接口开启驱动改写:把行级往返与提交压缩成批级。

SHOW FULL PROCESSLIST 定位运行中查询

实时查看连接正在执行什么:结合 Time、State 与 Info 列找卡住的语句;输出只是当前时刻快照,需要多次观察。

LIKE 前置通配与替代方案

LIKE 'abc%' 可走索引,'%abc' 走不了:按业务选择全文检索、反转列或 trigram 索引等替代方案。

在线创建索引:INPLACE 与 CONCURRENTLY

生产环境加索引要控制阻塞:MySQL 8.0 用 ALGORITHM/LOCK 子句约束在线 DDL;PostgreSQL 用 CREATE INDEX CONCURRENTLY。

COUNT 的精确成本与近似替代

COUNT(*) 需要扫描符合条件的行:InnoDB 选择较小的索引扫描;海量数据考虑近似值与维护计数表。

消除排序步骤的常见手法

让 ORDER BY 能按索引顺序取数:列序列、方向、条件都要匹配;否则数据库要收集后排序。

按主键分批更新大表

大范围 UPDATE 会长时间持锁、生成大事务:按主键区间循环小批执行,控制锁与回滚规模。

EXPLAIN 中的表访问顺序

多表连接时 EXPLAIN 按访问顺序逐行列出:同 id 的行属于同一查询块,自上而下就是连接发生顺序。

PG 计划相关参数速览

work_mem、random_page_cost、effective_cache_size 影响计划选择:按实例与存储特性调整,enable_* 仅用于诊断。

基数与区分度:索引值不值得

Cardinality 是索引列不同值的估算数:区分度低(性别、状态)的单列索引帮助有限,组合列或改写更有效。

子查询改写为连接的取舍

IN/EXISTS 子查询与 JOIN 在多数优化器下可得到等价执行:语义差异(去重、NULL)决定改写方向。

避免 SELECT *

需要什么列就写什么列:减少 IO 与网络传输,保住覆盖索引机会,也让代码对表结构变更更稳健。

死锁日志解读与预防

SHOW ENGINE INNODB STATUS 的 LATEST DETECTED DEADLOCK 段记录最近死锁的事务与等待;根本对策是统一加锁顺序、缩短事务。

执行计划突变排查思路

同一条 SQL 变慢但语句没改:先看计划是否变化,再查统计信息、数据分布与参数化因素。

mysqldumpslow 汇总慢日志

把慢日志按语句模板聚合排序:日志很大时先找出现次数多、总耗时高的模板,再回日志核对具体参数。

不可见索引:上线前验证删索引

MySQL 8.0 支持把索引设为 INVISIBLE:优化器忽略它但索引仍被维护,用于验证“删掉这个索引会不会变慢”。

全文索引与 MATCH AGAINST

按词做文本检索:MySQL 的 FULLTEXT(InnoDB 支持)与 PostgreSQL 的 tsvector + GIN 都能避开前置通配的全扫描。

GROUP BY 的执行方式与索引

分组可通过索引顺序、排序或哈希完成:EXPLAIN 显示临时表或排序时,优先考虑让分组借用索引。

UNION 与 UNION ALL 的成本差异

UNION 默认去重:需要临时表或排序去重;UNION ALL 直接拼接,配合外层排序与 LIMIT 更省。

sys.innodb_lock_waits 找阻塞源头

锁等待排查:等待方、阻塞方、阻塞语句与等待时长在一个视图里,直接定位谁在挡谁。

Handler 与 InnoDB 行计数解读

Handler_read_rnd_next、Innodb_rows_read 等计数从扫描行为侧面验证 EXPLAIN 的结论,用增量对比才有意义。

auto_explain 自动记录慢查询计划

把超过阈值的语句连同执行计划写进日志:事后分析线上慢查询时不用手动复现。

前缀索引:长字符串列的折中

长字符串列只索引前 N 个字符:减小索引体积,但无法覆盖查询,也不能完全替代整列排序用途。

OR 条件与索引利用

同列多个等值条件优先写成 IN;跨列 OR 往往触发索引合并或全表扫描,改写 UNION 更可控。

找出未使用与冗余索引

判断索引是否值得保留:MySQL 用 sys 视图,PostgreSQL 用 pg_stat_user_indexes 的扫描计数。

唯一索引与普通索引怎么选

唯一索引承担业务约束、等值查找命中即停;普通索引允许重复值、用于支撑查询。约束真与查询快是两件事。

派生表合并与物化(derived_merge)

MySQL 5.7+ 会把 FROM 子查询合并进外层查询(受阻时物化成临时表):用 EXPLAIN 辨别两种形态。

连接数与连接池观察

连接不是越多越好:数据库侧连接开销(线程或进程、内存)与应用池配置要匹配,短事务配够用的小池。

索引合并 index_merge

OR 或多条件组合命中多个单列索引时,优化器可分别扫描再合并结果(Extra: Using intersect/union);它常提示单列索引需要组合成复合索引。

NULL 值与索引使用

IS NULL 通常可走索引;负向条件(<>、NOT IN、NOT LIKE)容易退回扫描,能否走索引以实际计划为准。

PostgreSQL 表达式索引

把表达式结果建进索引:lower(email)、(timestamp_col::date) 等查询条件可直接命中,前提是表达式完全一致。

USE / IGNORE / FORCE INDEX 表提示

在表名后声明索引提示:强制、忽略或限定候选索引,用来复现计划或临时规避优化器误判。

MySQL 8.0 优化器提示 /*+ */

语句级提示:INDEX/NO_INDEX 控制索引、JOIN_ORDER 固定连接顺序、SET_VAR 临时改会话变量、MAX_EXECUTION_TIME 限制执行时长。

缓冲池命中率与物理读

Innodb_buffer_pool_reads 是磁盘读取页数、read_requests 是请求总数:两者比值反映读命中情况。

表空间回收与重建:OPTIMIZE / VACUUM FULL

大量删除后空间不一定归还:MySQL 的 OPTIMIZE TABLE 对 InnoDB 近似重建表;PostgreSQL 用 VACUUM FULL 或 pg_repack。

pt-query-digest 分析慢日志

Percona Toolkit 的聚合分析工具:按查询模板给出耗时分布、次数与示例,适合大日志的常态化分析。

JSON 多值索引(8.0.17+)

为 JSON 数组的每个元素建立索引条目:让 MEMBER OF、JSON_CONTAINS 等条件可以走索引。

跳跃扫描 skip scan(8.0.13+)

未使用联合索引前导列时,优化器可对前导列的少量取值逐个“跳跃”扫描:Extra 显示 Using index for skip scan。

降序索引(MySQL 8.0)

8.0 起支持真正的降序索引:多列混合排序方向(如 a ASC, b DESC)可被索引直接满足,避免额外排序。

PostgreSQL 部分索引

只索引满足条件的数据行:过滤条件固定、热点数据占比低的查询(如未完成订单)能显著缩小索引。

直方图统计(MySQL 8.0)

为无索引列或分布不均的列生成直方图:优化器据此估算过滤比例,改善访问路径选择。

只读副本延迟与读写分离注意

读副本承担只读流量时要监控复制延迟与一致性:写后立即读可能读到旧数据。

分区裁剪:让查询只扫目标分区

按分区键的常量条件定位分区:EXPLAIN 中会显示裁剪结果,分区键上的函数往往阻止裁剪。

哈希索引的适用边界

哈希索引只支持等值查找,不支持范围与排序:MySQL 的 Memory 引擎可显式建哈希索引,InnoDB 的自适应哈希索引由引擎内部管理。

PostgreSQL INCLUDE 覆盖列

把仅用于返回的列放进 INCLUDE 子句:既能支撑 Index Only Scan,又不参与键排序与去重。

InnoDB 持久化统计信息

统计信息落盘并可配置采样:8.0 默认持久化,重启后不丢;理解自动重算与采样页数有助于计划稳定。

没有匹配的条目。换个关键词试试,或直接全站搜索。
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌