SQL数据库高基数字段索引_选择性评估方法

12次阅读

高基数字段是否建索引关键看选择性(满足条件行数/总行数),理想值趋近0;一般<5%适合索引,>20%优化器常弃用;需结合查询模式、统计信息准确性和分布倾斜度综合判断。

SQL数据库高基数字段索引_选择性评估方法

高基数字段是否值得建索引,不能只看“唯一值多”,关键要看选择性(selectivity)——即查询时能过滤掉多少数据。选择性越高,索引效率越明显;反之,即使字段唯一值上百万,若常用查询条件匹配大量行,索引可能被优化器弃用。

什么是选择性?怎么算?

选择性 = 满足条件的行数 / 表总行数(理想值趋近于 0,越小越好)。例如:用户表 1000 万行,user_id 是主键,查单个 ID 的选择性是 1/10000000 ≈ 0.0000001;而 status 字段有 3 个值且分布均匀,查 status = 'active' 的选择性约为 0.33。

  • 一般认为选择性 才较适合走索引
  • 超过 0.2(20%)时,全表扫描往往更快,优化器大概率忽略该索引
  • 计算示例:SELECT count(*) Filter (WHERE status = 'pending') * 1.0 / COUNT(*) FROM users;postgresql)或用子查询兼容 mysql

别只看全局基数,要看实际查询模式

一个字段整体唯一值很多(如订单号、设备 ID),但业务查询常带时间范围或状态前缀,真实过滤效果取决于组合条件下的有效选择性

  • 比如 order_no 全局唯一,但查询 WHERE order_no LIKE '202410%' 可能命中上万条——此时单独对 order_no 建索引无意义
  • 更优做法:把高频过滤字段(如 created_at)放在联合索引左侧,再加 order_no,让索引能快速定位时间窗口内的数据
  • EXPLaiN ANALYZE 看执行计划中 Rows Removed by Filter 占比,比理论值更真实

统计信息要准,否则评估会失真

优化器依赖表和列的统计信息估算选择性。如果 ANALYZE(PostgreSQL)或 UPDATE STATISTICS(SQL Server)长期未执行,或采样率过低,可能导致误判。

  • 检查统计信息新鲜度:pg_stat_all_tables.last_analyze(PG);sys.dm_db_stats_properties(SQL Server)
  • 对高基数字段,建议提高采样率(如 PG 中 ALTER TABLE t ALTER column c SET STATISTICS 1000
  • 避免在 WHERE 中对字段做函数操作(如 YEAR(created_at) = 2024),这会让统计失效,也使索引无法使用

用直方图+NDV交叉验证更可靠

仅靠 COUNT(DISTINCT) 不够——它不反映分布倾斜。比如用户地区字段有 200 个唯一值,但 80% 数据集中在 3 个省份,查其余 197 个值的选择性极好,查那 3 个却很差。

  • 查看列直方图(PostgreSQL 的 pg_stats 表、MySQL 的 information_schema.COLUMN_STATISTICS)了解值分布
  • 结合 ndvnumber of Distinct Values)和常见值频次,识别“长尾”还是“尖峰”分布
  • 对倾斜字段,可考虑分区 + 局部索引,或为高频值建覆盖索引,低频值走默认路径
text=ZqhQzanResources