UUID、空间类型与扩展

共 53 题
📑 题目列表 53 题
#
★★★

1. MySQL 中 UUID 与 BINARY(16) 存储的性能差异?

请说明 MySQL 中把 UUID 存为 CHAR(36) 与 BINARY(16) 的性能差异?

  • 存储空间
  • 索引大小
  • 转换

UUID 若存为 CHAR(36) 字符串占 36 字节,存为 BINARY(16) 只占 16 字节,后者显著省空间、索引更小更快。把 UUID 字符串转 BINARY(16) 需去除连字符并转十六进制,可用 UNHEX(REPLACE(uuid,'-',''))。BINARY(16) 作为主键/索引键更高效。但需在应用层维护转换。空间与索引优势是 BINARY(16) 的关键。

BINARY(16) 比 CHAR(36) 省一半以上空间,索引与存储性能更优,是 UUID 存储的推荐方式。

INSERT INTO t (id) VALUES (UNHEX(REPLACE('550e8400-...', '-', '')));
SELECT HEX(id) FROM t;
#
★★★

2. PostgreSQL 中 uuid 类型的存储与 gen_random_uuid() 函数?

请说明 PostgreSQL 中 uuid 类型的存储与 gen_random_uuid() 函数?

  • 原生 uuid 类型
  • 16 字节
  • gen_random_uuid

PostgreSQL 有原生 uuid 类型,固定 16 字节存储,适合作为主键。gen_random_uuid() 生成 UUID v4(随机),PG 13+ 内置(pgcrypto 之外的 core 函数),PG 13 之前需用 pgcrypto 扩展或 uuid-ossp。可用作列默认值:id uuid DEFAULT gen_random_uuid()。uuid 类型比文本存储更紧凑、比较更快。

PostgreSQL 原生 uuid 类型 16 字节 + gen_random_uuid(),是分布式环境理想的随机主键。

CREATE TABLE t (id uuid DEFAULT gen_random_uuid() PRIMARY KEY);
#
★★★

3. UUID v7 的优势,时间序递增,索引写入友好?

请说明 UUID v7 的优势:时间序递增、对索引写入友好?

  • 时间序前缀
  • 索引局部性
  • 随机性

UUID v7 以 48 位 Unix 时间戳为前缀,后接随机部分,因此同一毫秒内生成的 UUID 时间上递增,写入数据库时页面顺序接近,减少 B+Tree 页分裂与随机 IO,对索引写入友好。相比 UUID v4 的完全随机导致写入分散,v7 兼具随机主键分布与时间局部性,是分布式环境较新的推荐主键。v7 在 PG 18+ 提供 uuidv7() 函数生成。

v7 用时间序前缀解决 v4 的随机写入问题,同时保留足够随机性,兼顾安全与性能。

#
★★★

4. UUID 作为主键的优势与劣势,写入分散(无热点)vs 索引空间(16 字节 vs 8 字节)?

请说明 UUID 作为主键的优势与劣势,特别是写入分散与索引空间?

  • 随机主键分布
  • 16 字节 vs 8 字节
  • 页分裂

UUID 作为主键的优势:全局唯一、无自增依赖、可离线生成、无热点(写入分布均匀)。劣势:索引空间大(16 字节 vs BIGINT 8 字节),随机值导致 B+Tree 页分裂与随机 IO,写入性能下降,且主键插入顺序无序。折中:用 BIGINT 自增或雪花 ID 保序,或用 UUID v7 兼顾随机与顺序。索引空间翻倍也会增大缓存压力。

UUID 以索引空间与写入随机性换全局唯一与无热点,v7 可缓解写入问题。

#
★★★

5. BIGINT 与 UUID 的存储对比?

请对比 BIGINT 与 UUID 作为主键的存储与性能?

  • 8 字节 vs 16 字节
  • 顺序 vs 随机
  • 场景

BIGINT 主键占 8 字节,自增有序,索引紧凑、写入快、无页分裂,但依赖自增、跨库不易全局唯一、可能被枚举遍历;UUID 主键占 16 字节,全局唯一、无依赖、可离线生成,但索引大、写入随机。取舍:单库高写入可选 BIGINT/雪花 ID,需全局唯一或分布式可选 UUID。BIGINT 空间与写入性能更优,UUID 在唯一性与分布式上更优。

BIGINT 以空间与顺序性见长,UUID 以唯一性与分布式见长,选择取决于部署形态。

#
★★★

6. MySQL 中 UUID() 函数?

请说明 MySQL 中 UUID() 函数的作用?

  • 生成 UUID
  • 格式
  • 与 UUID_SHORT

MySQL 的 UUID() 返回一个 UUID v1 格式的字符串(形如 550e8400-e29b-41d4-a716-446655440000),基于时间戳。UUID_SHORT() 返回一个 64 位整数。UUID() 返回的字符串可转 BINARY(16) 存储。UUID() 基于服务器时间,分布式多实例可能重复的顾虑较小但需注意。MySQL 8 无原生 uuid 类型,UUID 通常存 CHAR(36) 或 BINARY(16)。

MySQL 用 UUID() 函数生成字符串 UUID,配合 BINARY(16) 存储以优化空间。

#
★★★

7. PostgreSQL 中 UUID 与文本比较?

请说明 PostgreSQL 中 UUID 类型与文本类型比较的差异?

  • 原生类型 vs 文本
  • 存储与比较
  • 转换

PostgreSQL 的 uuid 类型存储 16 字节,比较按二进制字节序,比文本(CHAR/VARCHAR)的字符串比较更快、存储更小。文本存储 UUID 会占 36 字节且比较慢。uuid 类型还校验格式合法性。查询时文本需 cast 为 uuid(如 WHERE id = 'uuid-string'::uuid)。因此存 UUID 推荐原生 uuid 类型而非文本。

原生 uuid 类型在存储、比较、校验上全面优于文本,是 UUID 存储的正确选择。

SELECT id FROM t WHERE id = '550e8400-...'::uuid;
#
★★★

8. PostGIS 扩展(PostgreSQL)的空间数据模型,Point、LineString、Polygon、MultiPolygon?

请说明 PostGIS 的空间数据模型:Point、LineString、Polygon、MultiPolygon?

  • 几何类型
  • 组成
  • 用途

PostGIS 基于 OGC/ISO 标准提供几何类型:Point(点,单坐标)、LineString(线,点序列)、Polygon(多边形,闭合环)、MultiPoint/MultiLineString/MultiPolygon(多元素集合)、GeometryCollection(混合集合)。这些类型表示空间对象,配合 SRID 与坐标函数使用。Point 表示坐标点,LineString 表示路径/线,Polygon 表示区域,MultiPolygon 表示多块区域(如国家边境)。

几何类型是空间建模的基础,单/多元素类型对应不同空间对象粒度。

#
★★★

9. 空间索引,R-Tree(PostGIS、MySQL InnoDB)、GiST 的取舍?

请说明空间索引中 R-Tree 与 GiST 的取舍?

  • R-Tree 概念
  • GiST 实现
  • 各数据库

R-Tree 是专为空间数据设计的树状索引,用最小边界矩形(MBR)组织空间对象;PostGIS 在 PostgreSQL 上通过 GiST 实现空间索引(GiST 支持 R-Tree 式操作),MySQL InnoDB 也提供空间索引。GiST 比 R-Tree 更通用、可扩展,支持复杂操作符与数据类型。取舍:GiST 是 PostgreSQL 的空间索引标准,支持高效的空间查询(相交、包含、距离);R-Tree 是传统空间索引结构,InnoDB 内置。二者都用于加速空间查询。

GiST 是 R-Tree 思想的通用实现,PostGIS 用 GiST 承载空间索引,MySQL InnoDB 用 R-Tree。

#
★★★

10. MySQL 8.0 的空间函数增强?

请说明 MySQL 8.0 在空间函数上的增强?

  • ST_* 函数
  • 空间支持
  • 性能

MySQL 8.0 增强了空间功能:支持 SRID 列定义、更多 ST_* 空间函数(ST_Distance、ST_Within、ST_Contains、ST_Intersects 等)、空间索引改进、空间参考系统支持。8.0 引入 SRID 语法与基于内部空间数据结构的优化。相比早期版本,8.0 的空间查询正确性与性能显著提升,但仍不如 PostGIS 全面。

MySQL 8.0 的空间能力大幅增强(SRID、ST_* 函数、空间索引),是空间选择的改善点。

#
★★★

11. MySQL 中 ST_GeomFromText 的函数?

请说明 MySQL 中 ST_GeomFromText 函数的作用与用法?

  • WKT 解析
  • 几何构造
  • 语法

ST_GeomFromText(wkt, [srid]) 把 WKT(Well-Known Text)字符串解析为几何对象。WKT 是标准空间文本格式,如 ST_GeomFromText('POINT(1 2)')ST_GeomFromText('POLYGON((0 0,0 1,1 1,1 0,0 0))')。可指定 SRID 第二参数。它是构造几何对象并进行后续空间运算的入口。PostGIS 中对应 ST_GeomFromText。

WKT 是空间对象的文本表示,ST_GeomFromText 是 WKT→几何的转换函数。

SELECT ST_GeomFromText('POINT(1 2)', 4326);
#
★★★

12. MySQL 空间索引的存储引擎要求?

请说明 MySQL 空间索引的存储引擎要求?

  • InnoDB 支持
  • MyISAM
  • 版本

MySQL 的空间索引要求:MyISAM 与 InnoDB 都支持空间索引,但 InnoDB 的 R-Tree 空间索引在 MySQL 5.7+ 可用,8.0 更完善。空间列(如 GEOMETRY)上的索引称为 SPATIAL INDEX,要求列是 NOT NULL。InnoDB 支持 SRID 与空间索引。创建语法 CREATE SPATIAL INDEX ... ON t (geom)。空间索引用于加速空间查询。

空间索引要求列 NOT NULL 且使用 SPATIAL INDEX 语法,InnoDB/MyISAM 均支持。

CREATE TABLE t (geom GEOMETRY NOT NULL SRID 4326, SPATIAL INDEX idx (geom));
#
★★★

13. PostGIS 中 GIST 索引的创建?

请说明 PostGIS 中如何创建 GIST 空间索引?

  • GIST 语法
  • 空间列
  • 查询加速

PostGIS 中为几何列创建 GIST 索引:CREATE INDEX idx ON t USING gist (geom);。GIST 索引加速空间操作符(如 &&、ST_Intersects、ST_DWithin、ST_Within),是空间查询高性能的关键。几何列通常用 geography 或 geometry 类型,GIST 索引支持两者。创建后空间查询可走索引避免全表扫描。

GIST 索引是 PostGIS 空间查询的引擎,创建语法简单,查询时自动用于空间操作符。

CREATE INDEX idx_geom ON places USING gist (geom);
SELECT * FROM places WHERE ST_DWithin(geom, ST_SetSRID(ST_MakePoint(1,2),4326), 0.1);
#
★★★

14. 空间函数 ST_Area、ST_Length 的单位?

请说明 PostGIS 中 ST_Area、ST_Length 的单位?

  • geometry 单位
  • geography 单位
  • SRID 影响

ST_Area、ST_Length 的返回值单位取决于几何类型:geometry 类型按坐标系统单位返回(如经纬度 4326 下面积为"平方度"、长度为"度"),不是物理单位;geography 类型按米计算(球面),返回米或平方米。因此用经纬度查询面积/长度时,用 geography 或对 geometry 做投影(ST_Transform 到投影坐标系)才能得到米/平方米。单位选择直接影响结果理解。

geometry 用坐标单位、geography 用米,经纬度需投影或 geography 才能得物理单位。

#
★★★

15. 空间索引的 WHERE 子句要求?

请说明空间索引在 WHERE 子句中的使用要求?

  • 空间操作符
  • 索引可用
  • 函数形态

空间索引要在 WHERE 子句中生效,需使用可空间索引的操作符或函数形态,如 && 、ST_Intersects、ST_DWithin、ST_Within 等,且几何列出现在函数参数中。PostgreSQL 可识别这些操作符并利用 GIST 索引。若使用不可索引的函数或对列做非确定性变换,则退化为全表扫描。保持几何列 NOT NULL 且 SRID 一致有助于索引使用。

空间索引可用依赖"可索引的操作符/函数 + 几何列直用",否则全表扫描。

#
★★★

16. MySQL 中 GEOMETRY 类型的应用?

请说明 MySQL 中 GEOMETRY 类型的应用场景?

  • 几何类型
  • 空间查询
  • 应用

MySQL 的 GEOMETRY 类型是空间数据基类,可存储 Point、LineString、Polygon 等。应用场景:地图 POI(点)、路线(线)、区域(多边形)、地理围栏等。通过 ST_* 函数与空间索引做距离、包含、相交查询。MySQL 8.0 支持 SRID 与空间索引,适合轻量空间需求。但复杂空间分析不如 PostGIS 全面。

GEOMETRY 用于存储与查询空间对象,MySQL 8 空间能力增强但复杂分析仍逊 PostGIS。

#
★★★

17. CREATE TYPE 在 PostgreSQL 中的四种类型,composite、enum、range、base?

请说明 CREATE TYPE 在 PostgreSQL 中创建的四种类型:composite、enum、range、base?

  • 四种类型
  • 语法
  • 用途

PostgreSQL 的 CREATE TYPE 可创建四类类型:composite(复合类型,如 CREATE TYPE comp AS (a int, b text))、enum(枚举,CREATE TYPE mood AS ENUM ('sad','ok'))、range(范围,CREATE TYPE price_range AS RANGE (subtype=numeric))、base(基础/自定义标量类型,需输入输出函数,最复杂)。它们分别用于聚合字段、受限取值、区间、自定义标量。enum 是常见、range 用于区间、composite 用于结构、base 需底层实现。

四种 CREATE TYPE 对应不同自定义类型需求,base 类型需 C 函数实现最复杂。

#
★★★

18. UUID 随机主键导致 B+Tree 页分裂与随机 IO 的原理,及 UUID v7/有序化改写的取舍

请说明 UUID 随机主键导致 B+Tree 页分裂与随机 IO 的原理,以及 UUID v7/有序化改写的取舍?

  • 随机插入与页分裂
  • 随机 IO
  • v7 有序化

随机 UUID 主键插入时,新键落在 B+Tree 的任意位置,需频繁写入中间页,导致页分裂(page split)、索引碎片与缓存未命中,写入产生随机 IO,性能下降。有序化改写(如 UUID v7,时间戳前缀)使新键接近当前最大值,顺序写入触及热页,减少页分裂与随机 IO,提升写入性能。但 v7 仍保留随机部分,安全性优于纯自增。取舍:高写入场景用 v7 或雪花 ID 保序,纯 v4 随机虽分布均匀但写入昂贵。

随机主键的写入成本来自"顺序插入 vs 随机插入"的 B+Tree 特性,v7 用时间戳前缀恢复顺序性。

#
★★

19. 基础类型(Base Type)的创建,输入/输出函数、类型修饰符、内部长度?

请说明 PostgreSQL 中基础类型(Base Type)的创建要素?

  • 输入输出函数
  • 类型修饰符
  • 内部长度

创建基础类型(base type)需提供 I/O 函数(把文本转成内部表示、内部表示转回文本),并用 CREATE TYPE 指定 internallength、alignment、storage、category 等属性。可选类型修饰符(如长度 n)通过 typmod 处理。基础类型是最底层的自定义类型,通常用 C 语言实现输入输出函数,复杂度高。应用级自定义类型多用 composite/enum/range。

base 类型需 C 级 I/O 函数与内部布局,是自定义类型中最复杂的一类。

#
★★

20. 复合类型(Composite Type)的创建与使用,CREATE TYPE comp AS (a int, b text)?

请说明 PostgreSQL 中复合类型的创建与使用?

  • 复合类型语法
  • 行构造
  • 字段访问

复合类型用 CREATE TYPE comp AS (a int, b text) 创建,表示一组字段的结构。可用来定义列类型、函数参数或返回类型。可用行构造 ROW(1,'x')(1,'x') 创建实例,字段访问用 (row).arow.a。复合类型常用于表结构复用、函数返回多列、或者把多字段封装为单值传递。

复合类型把字段集合封装为类型,可与行构造、字段访问配合使用。

CREATE TYPE comp AS (a int, b text);
CREATE TABLE t (c comp);
SELECT (c).a, (c).b FROM t;
#
★★

21. 自定义类型对 ORM 框架的影响,Hibernate、SQLAlchemy、PostgreSQL JDBC?

请说明自定义类型对 ORM 框架(Hibernate、SQLAlchemy、PostgreSQL JDBC)的影响?

  • 类型映射
  • 自定义类型注册
  • 兼容性

自定义类型(enum、composite、range 等)在 ORM 中通常不在默认映射范围,需要显式注册或自定义映射。Hibernate 需用 hibernate-types 或 @JdbcTypeCode/@Type 映射 enum/range;PostgreSQL JDBC 需注册 PGobject 或使用 org.postgresql.util.PGobject 处理自定义类型;SQLAlchemy 可用 TypeDecorator/UUID 等。未映射会导致读取失败或类型不匹配。因此使用自定义类型会增大 ORM 集成成本。

自定义类型需 ORM 显式映射,否则读取/写入异常,是使用自定义类型的额外成本。

#
★★

22. 扩展的升级与卸载(ALTER EXTENSION UPDATE)?

请说明 PostgreSQL 中扩展的升级与卸载(ALTER EXTENSION UPDATE)?

  • 升级扩展
  • 卸载
  • 版本

升级扩展用 ALTER EXTENSION name UPDATE TO 'new_version',按扩展提供的升级脚本应用新版本。卸载用 DROP EXTENSION name(可加 CASCADE 去除依赖对象)。升级前应确认兼容性并备份,部分扩展升级可能需重建依赖对象。pg_available_extensions 可查看可升级版本。

ALTER EXTENSION UPDATE 升级、DROP EXTENSION 卸载,是扩展生命周期管理。

ALTER EXTENSION postgis UPDATE TO '3.4.0';
DROP EXTENSION IF EXISTS hstore;
#
★★

23. PostgreSQL 中 ltree 扩展的路径类型?

请说明 PostgreSQL 中 ltree 扩展的路径类型?

  • ltree 树路径
  • 语法
  • 查询

ltree 扩展提供层级路径类型,用点分隔的标签表示树形路径,如 Top.Science.Physics。支持祖先/后代查询(@> 包含、<@ 被包含、|| 连接、? 匹配模式),常用于分类树、目录树、组织架构等。ltree 有对应的 GIST/BTREE 索引加速路径查询。它是轻量级的树形路径解决方案。

ltree 用点分隔路径表示树,配合祖先/后代操作符与 GIST 索引高效查询树结构。

CREATE EXTENSION ltree;
CREATE TABLE t (path ltree);
SELECT * FROM t WHERE path @> 'Top.Science';
#
★★

24. UUID 的版本差异,v1(时间戳+MAC)、v4(随机)、v5(命名空间)、v7(时间序)?

请说明 UUID 各版本的差异:v1、v4、v5、v7?

  • 各版本生成方式
  • 用途
  • 特性

UUID v1 基于时间戳 + 节点(MAC)地址生成,时间有序但泄露 MAC 与创建时间;v4 完全随机生成,安全性高但无顺序;v5 基于命名空间 + 名称的 SHA-1 哈希生成,确定性(同一输入同 UUID);v7 以时间戳为前缀 + 随机后缀,时间有序且随机,兼顾安全与排序。v3 用 MD5,v5 用 SHA-1。选择:v4 通用随机,v7 适合作主键,v1 少用(隐私),v5 用于确定性标识。

各版本按"时间/随机/命名"区分,v7 是较新的时间序主键优选。

#
★★

25. Snowflake ID 的 64 位结构,时间戳(41)、机器(10)、序列(12)?

请说明 Snowflake ID 的 64 位结构:时间戳(41 位)、机器(10 位)、序列(12 位)?

  • 位分配
  • 时间戳高位
  • 单调性

Snowflake ID 是 64 位整数,结构通常为:1 位符号位(0)+ 41 位毫秒时间戳(约 69 年)+ 10 位机器 ID(5 位数据中心 + 5 位机器)+ 12 位序列号(每毫秒 4096 个)。时间戳在高位保证 ID 随时间递增,机器位保证多实例唯一,序列位处理同毫秒并发。整体有序、可排序、可解析出时间。广泛用于分布式主键生成。

位分配体现"时间有序 + 实例唯一 + 并发序列"三要素,是分布式 ID 的经典方案。

#
★★

26. UUID v1 的 MAC 地址泄露问题?

请说明 UUID v1 的 MAC 地址泄露问题?

  • v1 含 MAC
  • 隐私风险
  • 替代

UUID v1 的第 48 位节点字段直接使用网卡 MAC 地址,会泄露生成机器的物理地址,且同一机器生成的 v1 UUID 可被关联,存在隐私与安全风险。若必须用 v1,可配置随机节点(省去 MAC)。现代实践更推荐 v4(随机)或 v7(时间序),避免 MAC 泄露。

v1 的 MAC 字段是隐私隐患,多数场景改用 v4/v7 规避。

#
★★

27. gen_random_uuid 在 PG 13 之前的扩展?

请说明 gen_random_uuid 在 PostgreSQL 13 之前需要什么扩展?

  • PG 13 内置
  • pgcrypto
  • uuid-ossp

gen_random_uuid() 从 PostgreSQL 13 起成为核心内置函数,无需扩展。PG 13 之前需启用 pgcrypto 扩展(CREATE EXTENSION pgcrypto)才能使用 gen_random_uuid();也可用 uuid-ossp 扩展的 uuid_generate_v4()。因此旧版本部署需显式创建扩展。

gen_random_uuid 的内置是 PG13 的重要变化,旧版依赖 pgcrypto。

CREATE EXTENSION IF NOT EXISTS pgcrypto; -- PG13 之前
SELECT gen_random_uuid();
#
★★

28. 空间参考系(SRID)的概念,4326(WGS 84)、3857(Web Mercator)?

请说明空间参考系(SRID)的概念,特别是 4326(WGS 84)与 3857(Web Mercator)?

  • SRID 定义
  • 4326 经纬度
  • 3857 Web 投影

SRID(Spatial Reference Identifier)标识空间数据的坐标参考系。4326 是 WGS 84 地理坐标系,用经纬度(度)表示,是 GPS 与全球定位的标准;3857 是 Web Mercator 投影坐标系,基于米制,广泛用于 Web 地图(Google/OSM 瓦片)。不同 SRID 的坐标不能直接比较,需 ST_Transform 转换。选择 SRID 影响单位与计算精度。

SRID 决定坐标系、单位与投影,4326 经纬度、3857 地图投影是最常用的两个。

#
★★

29. 空间查询,ST_Within、ST_Contains、ST_DWithin、ST_Distance 的语义?

请说明 PostGIS 中 ST_Within、ST_Contains、ST_DWithin、ST_Distance 的语义?

  • 包含关系
  • 距离函数
  • 语义差异

ST_Within(a,b) 判断 a 是否完全在 b 内部;ST_Contains(b,a) 判断 b 是否完全包含 a(与 ST_Within 方向相反);ST_DWithin(a,b,d) 判断 a 与 b 的距离是否小于等于 d(d 为阈值,可用索引);ST_Distance(a,b) 返回 a 与 b 之间的最小距离。ST_Within/ST_Contains 是包含关系,ST_DWithin/ST_Distance 是距离关系,ST_DWithin 可走索引、ST_Distance 通常需先过滤。

区分"包含"与"距离"语义,ST_DWithin 用阈值且可走索引,ST_Distance 返回具体距离。

#
★★

30. 空间投影与坐标转换,ST_Transform 的应用?

请说明 PostGIS 中 ST_Transform 的应用?

  • 坐标转换
  • 投影
  • 用途

ST_Transform(geom, new_srid) 把几何对象从源 SRID 转换到目标 SRID,用于坐标投影转换。例如把 4326 经纬度转换到 3857 Web Mercator 或本地投影坐标系进行米制计算。也可调用 ST_Transform(geom, to_proj) 将地理坐标投影到平面。转换后单位与精度变化,可进行物理距离/面积计算。需确保源 SRID 正确。

ST_Transform 在不同坐标系间转换,是把经纬度转米制计算的关键。

SELECT ST_Transform(ST_SetSRID(ST_MakePoint(116,39),4326), 3857);
#
★★

31. PostGIS 中 Point 的构造?

请说明 PostGIS 中构造 Point 的方法?

  • ST_MakePoint
  • ST_GeomFromText
  • SRID

PostGIS 构造 Point 常用 ST_MakePoint(x, y) 生成 2D 点,或 ST_MakePoint(x, y, z)。也可用 ST_GeomFromText('POINT(x y)')。构造后通常用 ST_SetSRID 指定坐标系,如 ST_SetSRID(ST_MakePoint(116,39),4326)。geography 类型用 ST_SetSRID + ST_GeographyFromText 或 ST_MakePoint 后转 geography。Point 是空间查询的基础。

ST_MakePoint/ST_GeomFromText 构造点,ST_SetSRID 指定坐标系,是空间操作起点。

SELECT ST_SetSRID(ST_MakePoint(116.4, 39.9), 4326);
#
★★

32. PostGIS 中的栅格(raster)支持?

请说明 PostGIS 中的栅格(raster)支持?

  • raster 类型
  • 用途
  • 与 vector 区别

PostGIS 提供 raster 类型(PostGIS Raster 扩展,需单独启用),用于存储栅格数据(影像、DEM、分类图等由像素网格组成的数据)。与 vector(几何矢量)相对,raster 表示连续网格。raster 支持交集、裁剪、统计(ST_SummaryStats)、栅格与矢量运算(ST_Intersection)等。用于遥感影像、地形分析等。功能较复杂且需专门扩展。

raster 是栅格数据支持,与 vector 相对,用于影像与网格分析。

#
★★

33. ST_Contains 与 ST_Within 的关系?

请说明 PostGIS 中 ST_Contains 与 ST_Within 的关系?

  • 反向关系
  • 边界处理
  • 语义

ST_Contains(a,b) 与 ST_Within(b,a) 是逻辑等价的反向关系:若 a 包含 b,则 b 在 a 内部。即 ST_Contains(A,B) 等价于 ST_Within(B,A)。它们都基于"包含"语义,常用于判断几何对象的包含关系。细节上两者对边界点与内部定义一致,但注意空几何与边界情况。选方向取决于习惯,通常用 ST_Within(子, 父) 更直观。

ST_Contains 与 ST_Within 是同一关系的两个方向,参数交换即等价。

#
★★

34. 扩展(Extension)机制,CREATE EXTENSION postgis、pg_trgm、uuid-ossp?

请说明 PostgreSQL 扩展机制及 CREATE EXTENSION postgis、pg_trgm、uuid-ossp 的用途?

  • 扩展机制
  • 各扩展用途
  • 启用

PostgreSQL 扩展机制把一组函数、类型、索引操作符打包,用 CREATE EXTENSION 一键启用。postgis 提供空间类型与函数;pg_trgm 提供 trigram 相似度匹配与 GIN/GiST 索引,用于模糊搜索;uuid-ossp 提供 UUID 生成函数(v1/v3/v4/v5)。扩展需要在数据库内 CREATE EXTENSION 后使用,并可能需系统级包(如 postgresql-contrib)。

CREATE EXTENSION 是其用扩展,各扩展提供特定能力(空间、搜索、UUID)。

CREATE EXTENSION postgis;
CREATE EXTENSION pg_trgm;
CREATE EXTENSION "uuid-ossp";
#
★★

35. CREATE EXTENSION postgis 的安装?

请说明 CREATE EXTENSION postgis 的安装步骤?

  • 系统包
  • 数据库扩展
  • 权限

安装 PostGIS 需两步:1) 系统层面安装 postgis 软件包(apt/yum 安装 postgresql-XX-postgis-XX);2) 在目标数据库执行 CREATE EXTENSION postgis;(有时还需 postgis_topology)。CREATE EXTENSION 需数据库超级用户或相应权限。完成后可创建空间表、使用 ST_* 函数。若需 raster 功能另启用 postgis_raster。

PostGIS 安装分"系统包 + 数据库扩展"两步,环境就绪后 CREATE EXTENSION 启用。

#
★★

36. CREATE TYPE AS ENUM 的语法?

请说明 PostgreSQL 中 CREATE TYPE AS ENUM 的语法?

  • 枚举创建
  • 值列表
  • 使用

CREATE TYPE AS ENUM 的语法:CREATE TYPE mood AS ENUM ('sad', 'ok', 'happy');。它创建枚举类型,值在括号内按顺序列出。之后可作为列类型、函数参数使用。枚举值顺序决定排序。增加值用 ALTER TYPE ADD VALUE(默认追加末尾)。删除值需重建类型。枚举值应为合法标识符且互相唯一。

枚举类型用 CREATE TYPE AS ENUM 创建,值顺序即排序顺序。

CREATE TYPE mood AS ENUM ('sad', 'ok', 'happy');
CREATE TABLE t (m mood);
#
★★

37. CREATE TYPE AS RANGE 的语法?

请说明 PostgreSQL 中 CREATE TYPE AS RANGE 的语法?

  • 范围类型创建
  • subtype
  • 操作符类

CREATE TYPE AS RANGE 的语法:CREATE TYPE price_range AS RANGE (subtype = numeric);CREATE TYPE tsrange_custom AS RANGE (subtype = timestamp, subtype_opclass = btree, collation = ...)。subtype 指定元素的标量类型,可选 subtype_opclass、collation、canonical 等。创建后可定义 range 列,配合内置的 range 操作符与 GiST 索引。内置 int4range、tsrange 等已覆盖常见需求。

自定义 range 类型通过指定 subtype 定义元素标量类型,适用于特定标量类型的区间。

CREATE TYPE price_range AS RANGE (subtype = numeric);
CREATE TABLE t (p price_range);
#
★★

38. DOMAIN 与 TYPE 的核心区别?

请说明 PostgreSQL 中 DOMAIN 与 TYPE 的核心区别?

  • 约束封装 vs 新类型
  • 复用
  • 使用

DOMAIN 基于现有类型的约束封装,如 CREATE DOMAIN email AS text CHECK (VALUE ~ '@'),它仍是原类型(可 cast、可索引),只是附加约束;TYPE 创建全新类型(composite/enum/range/base),与现有类型不同。DOMAIN 可复用约束、提高一致性,代价小;TYPE 创建新语义类型。区别核心:DOMAIN 是"带约束的别名",TYPE 是"新类型"。

DOMAIN 复用类型+约束,TYPE 定义新类型,DOMAIN 更轻量、更常用。

CREATE DOMAIN positive AS integer CHECK (VALUE > 0);
CREATE TABLE t (qty positive);
#
★★

39. 复合类型的访问((row_var).field)?

请说明 PostgreSQL 中复合类型字段的访问语法?

  • 括号访问
  • 字段引用
  • 歧义

复合类型字段访问用 (row).field 括号形式,必要时加括号避免歧义,如 (row).a(col).field。在 SQL 中,复合列字段可用 (t).at.a(若上下文明确)。行构造函数 (1,'x')ROW(1,'x') 创建复合值。字段访问结果是该字段类型。

括号包裹复合变量再取字段,是访问复合类型字段的标准语法。

SELECT (c).a, (c).b FROM t;
#
★★

40. 扩展的管理(pg_available_extensions)?

请说明 PostgreSQL 中 pg_available_extensions 视图的用途?

  • 可用扩展列表
  • 已安装状态
  • 版本

pg_available_extensions 视图列出系统可用的所有扩展及其信息,包括 name、default_version、installed_version、comment。它用于查看可安装/可升级的扩展及版本。例如查询哪些扩展可用、当前安装版本。已安装的扩展也有版本身份。配合 CREATE EXTENSION 安装、ALTER EXTENSION UPDATE 升级。

pg_available_extensions 是扩展的可视化目录,展示可用与已安装版本。

SELECT name, default_version, installed_version FROM pg_available_extensions;
#
★★

41. 自定义类型在 PL/pgSQL 中的使用?

请说明自定义类型在 PL/pgSQL 中的使用?

  • 类型声明
  • 变量
  • 返回

PL/pgSQL 中可使用自定义类型(composite、enum、range 等):声明变量为自定义类型,如 v my_composite;v mood;,用 v := ROW(1,'x') 赋值,字段访问 v.field。函数可返回自定义类型或用 RECORD 返回复合行。自定义类型使 PL/pgSQL 函数更类型安全、可读。枚举可用于比较,range 用于区间逻辑。

自定义类型在 PL/pgSQL 中作为变量/返回类型,增强类型安全与结构表达。

CREATE FUNCTION f(IN m mood) RETURNS mood AS $$
BEGIN
  RETURN m;
END $$ LANGUAGE plpgsql;
#
★★

42. Leaf 分布式 ID 生成器?

请说明 Leaf 分布式 ID 生成器的原理?

  • 号段模式
  • Snowflake 模式
  • 与雪花 ID

Leaf 是美团开源的分布式 ID 生成器,提供两种模式:Leaf-segment(号段模式)用数据库号段缓存,从 DB 取一批 ID 段缓存到内存,减少 DB 访问,可扩展;Leaf-snowflake 基于雪花算法,用服务实例分配 workId,生成 64 位有序 ID。号段模式依赖 DB 但有批量缓存,雪花模式无 DB 依赖但需时钟同步。Leaf 解决雪花 ID 的时钟回拨与号段模式的 DB 压力。

Leaf 整合号段与雪花两种策略,兼顾 DB 依赖与性能,是分布式 ID 的工程化方案。

#
★★

43. TinyURL 与 UUID 的取舍?

请说明 TinyURL(短链接)与 UUID 的取舍?

  • 短链接特点
  • UUID特点
  • 场景

TinyURL 用短字符串(如 base62 编码)标识,短、可读、便于分享,常用自增 ID 或哈希转码生成,适合短链系统;UUID 是 128 位唯一标识,长、不可读,适合分布式全局唯一主键。取舍:需要短且可分享的标识用短链/base62 编码(转换自增 ID),需要全局唯一、无依赖的标识用 UUID。短链长度短但需保证唯一与碰撞处理,UUID 唯一性高但长。

短链追求"短可读可分享",UUID 追求"全局唯一",用途决定选择。

#
★★

44. ULID 与 UUID v7 在 48 位时间戳加随机后缀的布局、同毫秒内的排序性与二进制/字符串表示上的对比?

请对比 ULID 与 UUID v7 在布局、同毫秒排序性与表示上的差异?

  • 48 位时间戳
  • 随机后缀
  • 排序与表示

ULID 与 UUID v7 都采用 48 位时间戳 + 随机后缀的布局:ULID 为 48 位毫秒时间戳 + 80 位随机,编码为 26 字符 Crockford base32 字符串,可排序;UUID v7 为 48 位毫秒时间戳 + 74 位随机 + 4 位版本 + 2 位变体,标准 32 位十六进制表示。两者同毫秒内随机后缀导致不保证严格递增(仅总体时间序),但都按时间排序。ULID 字符串更紧凑、可读,UUID v7 是标准 UUID 格式、兼容 UUID 生态。排序性上两者都非严格可排序,需 128 位比较。

ULID 与 v7 都是"时间戳+随机",差异在编码表示与生态兼容,排序性都非严格。

#
★★

45. UUID v4 的随机性?

请说明 UUID v4 的随机性?

  • 122 位随机
  • 安全随机
  • 碰撞概率

UUID v4 除版本位(4 位)与变体位(2 位)外,其余 122 位由随机数生成,故约有 2^122 种可能,碰撞概率极低。生产环境应使用加密安全随机源(如 PostgreSQL 的 gen_random_uuid()、Java SecureRandom)。v4 安全性高、不可预测,是通用随机标识的默认选择,但无时间顺序。

v4 的 122 位随机位保证唯一性与不可预测性,随机源需安全。

#
★★

46. PostGIS 的 KNN 距离排序(<-> 操作符)与 GiST 索引加速

请说明 PostGIS 中 KNN 距离排序(<-> 操作符)与 GiST 索引加速的原理?

  • KNN 排序
  • <-> 操作符
  • GiST 加速

PostGIS 的 <-> 操作符返回两点间的距离,用于 KNN(最近邻)查询:ORDER BY geom <-> 'POINT(x y)' LIMIT 10 返回最近的 N 个对象。配合 GiST 索引,PostgreSQL 可做空间索引辅助的 KNN 扫描,避免全表排序,大幅加速"找最近点"查询。<-> 用于排序(KNN),与 ST_Distance 类似但可走索引。这是地理围栏、附近推荐的核心查询。

<-> KNN 排序 + GiST 索引实现最近邻加速,是"找最近"查询的高效方案。

SELECT name FROM places ORDER BY geom <-> 'POINT(116 39)' LIMIT 10;
#
★★

47. PostGIS 的 geography 与 geometry 类型差异(球面 vs 平面计算)

请说明 PostGIS 中 geography 与 geometry 类型的差异(球面 vs 平面计算)?

  • 计算模型
  • 单位
  • 使用

geometry 类型在平面坐标(投影)上计算,单位与坐标系单位一致(度或米),范围小、精度在局部可用;geography 类型在球面上计算(基于地球椭球),始终以米为单位,适合全球经纬度数据,距离/面积计算准确。geography 计算更慢但更符合地理真实。若数据是经纬度且需全球准确距离,用 geography;若已成投影坐标,用 geometry 更快。

geometry 平面、geography 球面,单位与精度差异决定选择,geo 准确但慢。

#
★★

48. 类型转换(CAST)的显式与隐式规则?

请说明 PostgreSQL 中类型转换(CAST)的显式与隐式规则?

  • 显式 CAST
  • 隐式转换
  • 赋值转换

PostgreSQL 类型转换分三类:显式 CAST(CAST(expr AS type)expr::type,无条件执行)、赋值转换(插入/更新时自动、有损时可能报错)、隐式转换(表达式求值时自动,仅限安全且无歧义的类型)。显式转换最可控,隐式转换由系统按类型分类选择。有损转换(如 numeric→int)通常需显式。理解规则避免意外类型转换或报错。

显式可信、隐式便捷但有损需显式,转换规则决定表达式类型行为。

SELECT '123'::int;                    -- 显式
SELECT CAST(1.9 AS int);              -- 1
#

49. GeoJSON 与空间类型的转换?

请说明 PostGIS 中 GeoJSON 与空间类型之间的转换?

  • ST_GeomFromGeoJSON
  • ST_AsGeoJSON
  • 格式

PostGIS 用 ST_AsGeoJSON(geom) 把几何对象转成 GeoJSON 格式(如 {"type":"Point","coordinates":[...]}),用 ST_GeomFromGeoJSON(json) 把 GeoJSON 解析为几何对象。GeoJSON 是 Web 地图交换的标准格式,常用于前端展示与 API 传输。转换时注意 SRID 通常为 4326。两者是空间数据与 GeoJSON 的桥梁。

ST_AsGeoJSON/ST_GeomFromGeoJSON 是几何与 GeoJSON 的双向转换,Web 地图常用。

SELECT ST_AsGeoJSON(ST_MakePoint(116,39));
SELECT ST_GeomFromGeoJSON('{"type":"Point","coordinates":[116,39]}');
#

50. 空间类型与 JSON 的取舍?

请说明空间类型与 JSON 存储空间数据的取舍?

  • 原生空间类型
  • JSON 存储
  • 查询能力

原生空间类型(geometry/geography)支持空间索引、空间函数与准确计算,是空间查询的正确选择;用 JSON 存坐标(如 {"lat":..,"lng":..})灵活性高、便于前后端一致,但无法做空间索引与高效空间查询,只能应用层计算。取舍:需要空间查询/分析用原生空间类型;仅存储坐标、无复杂空间查询且前端直接消费可用 JSON。但推荐坐标用原生类型 + SRID。

原生空间类型有索引与函数优势,JSON 灵活但无空间能力,按查询需求取舍。

#

51. DROP TYPE 的级联影响?

请说明 PostgreSQL 中 DROP TYPE 的级联影响?

  • 依赖对象
  • CASCADE
  • 后果

DROP TYPE 删除类型,若该类型被表列、函数、约束等引用,默认会报错;加 CASCADE 会级联删除所有依赖对象(可能删除表、函数、视图)。因此 DROP TYPE CASCADE 很危险,可能连表一起删。使用前应检查依赖(pg_depend),明确级联范围。删除枚举/复合类型尤需谨慎。

DROP TYPE 默认保护依赖,CASCADE 会级联删除依赖对象,风险高需谨慎。

#

52. 复合类型在 SELECT 中的构造?

请说明 PostgreSQL 中在 SELECT 里构造复合类型的方法?

  • ROW 构造
  • 复合值
  • 语法

在 SELECT 中可用 ROW(...) 或 (v1, v2, ...) 构造复合类型值,如 SELECT ROW(1, 'x') AS c;SELECT (1, 'x')::comp;。若类型需显式,可 cast。复合值可作为一行返回或作为字段。配合表名或类型转换可构造特定复合类型实例。这用于把多字段打包为单值。

ROW() 或括号列表构造复合类型,是 SELECT 中生成复合值的标准方式。

SELECT ROW(1, 'x')::comp AS c;
#

53. 扩展的兼容性(PG 版本)?

请说明 PostgreSQL 扩展与 PG 版本的兼容性?

  • 版本匹配
  • 扩展版本
  • 升级

扩展的可用性与能力与 PostgreSQL 版本相关:某些扩展仅特定版本可用(如 uuid 相关、PG 14 的 multirange),扩展也有自身版本号,需与 PG 版本匹配。系统包(如 postgresql-XX-postgis-XX)绑定 PG 版本。升级 PG 需同步升级扩展,ALTER EXTENSION UPDATE 升级到新版本。兼容性决定扩展可否安装与升级路径。

扩展与 PG 主版本绑定,升级需同步处理,兼容性影响可用性。