mfvanek/pg-index-health-sql
GitHub: mfvanek/pg-index-health-sql
一套纯 SQL 编写的 PostgreSQL 数据库 Schema 健康检查查询集,用于检测索引、表结构、外键和数据类型等方面的潜在问题并推动最佳实践落地。
Stars: 114 | Forks: 18
# pg-index-health-sql
**pg-index-health-sql** 是一个用于分析 PostgreSQL 模式、检测问题并推广最佳实践的 SQL 查询集合。
[](https://github.com/mfvanek/pg-index-health-sql/actions/workflows/linter.yml)
[](https://github.com/mfvanek/pg-index-health-sql/blob/master/LICENSE "Apache License 2.0")
## 这是什么?
**pg-index-health-sql** 提供了一组经过精心设计的原始 SQL 查询,旨在识别 PostgreSQL 数据库中常见的模式问题——例如冗余索引、缺少主键或低效的表结构。
它支持轻量级、数据库原生的分析,无需外部库或框架,适合直接在 psql 会话、脚本或监控仪表板中使用。
## 支持的 PostgreSQL 版本
[](https://www.postgresql.org/about/news/postgresql-14-released-2318/ "PostgreSQL 14")
[](https://www.postgresql.org/about/news/postgresql-15-released-2526/ "PostgreSQL 15")
[](https://www.postgresql.org/about/news/postgresql-16-released-2715/ "PostgreSQL 16")
[](https://www.postgresql.org/about/news/postgresql-17-released-2936/ "PostgreSQL 17")
[](https://www.postgresql.org/about/news/postgresql-18-released-3142/ "PostgreSQL 18")
### 支持先前版本的 PostgreSQL
不再保证与先前 PostgreSQL 版本的兼容性,但极有可能是兼容的。
我们仅关注当前处于维护期的 PostgreSQL 版本。
欲了解更多信息,请参阅 [PostgreSQL 版本控制策略](https://www.postgresql.org/support/versioning/)。
## 可用的检查项
**pg-index-health-sql** 允许您检测以下问题:
1. 无效(损坏)的索引 ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/invalid_indexes.sql))。
2. 重复(完全相同)的索引 ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/duplicated_indexes.sql))。
3. 交叉(部分相同)的索引 ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/intersected_indexes.sql))。
4. 未使用的索引 ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/unused_indexes.sql))。
5. 没有关联索引的外键 ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/foreign_keys_without_index.sql))。
6. 包含空值的索引 ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/indexes_with_null_values.sql))。
7. 缺少索引的表 ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/tables_with_missing_indexes.sql))。
8. 没有主键的表 ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/tables_without_primary_key.sql))。
9. 索引[膨胀](https://www.percona.com/blog/2018/08/06/basic-understanding-bloat-vacuum-postgresql-mvcc/) ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/bloated_indexes.sql))。
10. 表[膨胀](https://www.percona.com/blog/2018/08/06/basic-understanding-bloat-vacuum-postgresql-mvcc/) ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/bloated_tables.sql))。
11. 没有[描述](https://www.postgresql.org/docs/current/sql-comment.html)的表 ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/tables_without_description.sql))。
12. 没有[描述](https://www.postgresql.org/docs/current/sql-comment.html)的列 ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/columns_without_description.sql))。
13. [json](https://www.postgresql.org/docs/current/datatype-json.html) 类型的列 ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/columns_with_json_type.sql))。
14. 不是主键的 [serial 类型](https://www.postgresql.org/docs/current/datatype-numeric.html#DATATYPE-SERIAL) 列 ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/columns_with_serial_types.sql))。
15. 没有[描述](https://www.postgresql.org/docs/current/sql-comment.html)的函数 ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/functions_without_description.sql))。
16. [包含布尔值](https://habr.com/ru/companies/tensor/articles/488104/)的索引 ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/indexes_with_boolean.sql))。
17. 包含[无效约束](https://habr.com/ru/articles/800121/)的表 ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/not_valid_constraints.sql))。
18. [数组列上](https://habr.com/ru/articles/800121/)的 B-tree 索引 ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/btree_indexes_on_array_columns.sql))。
19. [序列溢出](https://habr.com/ru/articles/800121/) ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/sequence_overflow.sql))。
20. 使用 [serial 类型](https://wiki.postgresql.org/wiki/Don't_Do_This#Don.27t_use_serial)的主键 ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/primary_keys_with_serial_types.sql))。
21. 重复(完全相同)的外键 ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/duplicated_foreign_keys.sql))。
22. 交叉(部分相同)的外键 ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/intersected_foreign_keys.sql))。
23. 名称可能溢出的对象 ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/possible_object_name_overflow.sql))。
24. 未与其他表关联的表 ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/tables_not_linked_to_others.sql))。
25. [列类型不匹配的](https://habr.com/ru/articles/803841/)外键 ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/foreign_keys_with_unmatched_column_type.sql))。
26. 具有零个或一个列的表 ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/tables_with_zero_or_one_column.sql))。
27. 名称不符合命名约定的对象 ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/objects_not_following_naming_convention.sql))。
28. 名称不符合命名约定的列 ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/columns_not_following_naming_convention.sql))。
29. 使用 varchar 列而不是 uuids 的主键 ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/primary_keys_with_varchar.sql))。
30. [varchar(n)](https://www.postgresql.org/docs/current/datatype-character.html) 类型的列 ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/columns_with_fixed_length_varchar.sql))。
31. 在非空列上带有不必要 where 子句的索引 ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/indexes_with_unnecessary_where_clause.sql))。
32. 极有可能是自然键的主键 ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/primary_keys_that_most_likely_natural_keys.sql))。
33. [money](https://wiki.postgresql.org/wiki/Don%27t_Do_This#Don.27t_use_money) 类型的列 ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/columns_with_money_type.sql))。
34. [时间戳在中间的](https://habr.com/ru/companies/tensor/articles/488104/)索引 ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/indexes_with_timestamp_in_the_middle.sql))。
35. [timestamp](https://wiki.postgresql.org/wiki/Don't_Do_This#Don.27t_use_timestamp_.28without_time_zone.29) 类型的列 ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/columns_with_timestamp_or_timetz_type.sql))。
36. 主键列不是第一列的表 ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/tables_where_primary_key_columns_not_first.sql))。
37. 除主键外所有列均可为空的表 ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/tables_where_all_columns_nullable_except_pk.sql))。
38. [char(n) 类型](https://wiki.postgresql.org/wiki/Don%27t_Do_This#Don't_use_char(n) 的列 ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/columns_with_char_type.sql))。
39. 带有[继承](https://wiki.postgresql.org/wiki/Don%27t_Do_This#Don.27t_use_table_inheritance)的表 ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/tables_with_inheritance.sql))。
40. 多列外键中至少有一个引用列可为空 ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/foreign_keys_with_null_values.sql))。
## 本地开发
### Linting
#### macOS/Linux
要在本地运行 super-linter:
```
docker run \
-e RUN_LOCAL=true \
-e USE_FIND_ALGORITHM=true \
-e VALIDATE_SQLFLUFF=true \
-v $(pwd):/tmp/lint \
ghcr.io/super-linter/super-linter:slim-v8.6.0
```
#### Windows
在 Windows 上使用 `cmd`:
```
docker run ^
-e RUN_LOCAL=true ^
-e USE_FIND_ALGORITHM=true ^
-e VALIDATE_SQLFLUFF=true ^
-v "%cd%":/tmp/lint ^
ghcr.io/super-linter/super-linter:slim-v8.6.0
```
参见 https://github.com/super-linter/super-linter/blob/main/dependencies/python/sqlfluff.txt
```
docker run --rm ^
-v "%cd%\.github\linters\.sqlfluff":/sql/.sqlfluff:ro ^
-v "%cd%":/sql ^
-e SQLFLUFF_CONFIG=/sql/.sqlfluff ^
sqlfluff/sqlfluff:4.1.0 lint /sql
```
标签:PostgreSQL, psql, Schema分析, SQL, 主键检测, 健康检查, 冗余索引, 多线程, 开源, 性能优化, 数据库监控, 数据库索引, 数据库维护, 数据库质量, 最佳实践, 检测绕过, 模式分析, 测试用例, 系统审计, 表结构分析, 诊断工具, 请求拦截