{"id":15045057,"url":"https://github.com/mfvanek/pg-index-health","last_synced_at":"2025-04-13T05:06:00.898Z","repository":{"id":38332815,"uuid":"220783486","full_name":"mfvanek/pg-index-health","owner":"mfvanek","description":"pg-index-health is a Java library for analyzing and maintaining indexes and tables health in Postgresql databases.","archived":false,"fork":false,"pushed_at":"2025-04-12T19:15:54.000Z","size":3307,"stargazers_count":167,"open_issues_count":31,"forks_count":17,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-13T05:05:28.072Z","etag":null,"topics":["gradle","hacktoberfest","indexes","java","java-11","kotlin-dsl","mutation-testing","pitest","postgres","postgresql","static-analysis","testcontainers"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mfvanek.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"mfvanek"}},"created_at":"2019-11-10T11:58:39.000Z","updated_at":"2025-04-12T19:15:56.000Z","dependencies_parsed_at":"2023-10-05T10:31:13.579Z","dependency_job_id":"8e8cfc2b-f180-4eb1-8c93-f79530007fdc","html_url":"https://github.com/mfvanek/pg-index-health","commit_stats":{"total_commits":335,"total_committers":13,"mean_commits":25.76923076923077,"dds":0.4955223880597015,"last_synced_commit":"cafa2382a346d6b4c6b60dfa5281fa5c36ad9f7b"},"previous_names":[],"tags_count":35,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mfvanek%2Fpg-index-health","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mfvanek%2Fpg-index-health/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mfvanek%2Fpg-index-health/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mfvanek%2Fpg-index-health/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mfvanek","download_url":"https://codeload.github.com/mfvanek/pg-index-health/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248665749,"owners_count":21142123,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gradle","hacktoberfest","indexes","java","java-11","kotlin-dsl","mutation-testing","pitest","postgres","postgresql","static-analysis","testcontainers"],"created_at":"2024-09-24T20:51:24.170Z","updated_at":"2025-04-13T05:06:00.885Z","avatar_url":"https://github.com/mfvanek.png","language":"Java","funding_links":["https://github.com/sponsors/mfvanek"],"categories":["测试"],"sub_categories":[],"readme":"# ![pg-index-health](https://github.com/mfvanek/pg-index-health/blob/master/logo.png \"pg-index-health\")\r\n**pg-index-health** is a Java library for analyzing and maintaining indexes and tables health in [PostgreSQL](https://www.postgresql.org/) databases.\r\n\r\n[![Java CI](https://github.com/mfvanek/pg-index-health/actions/workflows/tests.yml/badge.svg)](https://github.com/mfvanek/pg-index-health/actions/workflows/tests.yml \"Java CI\")\r\n[![Maven Central](https://img.shields.io/maven-central/v/io.github.mfvanek/pg-index-health.svg)](https://search.maven.org/artifact/io.github.mfvanek/pg-index-health/ \"Maven Central\")\r\n[![License: Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/mfvanek/pg-index-health/blob/master/LICENSE \"Apache License 2.0\")\r\n[![javadoc](https://javadoc.io/badge2/io.github.mfvanek/pg-index-health/javadoc.svg)](https://javadoc.io/doc/io.github.mfvanek/pg-index-health \"javadoc\")\r\n[![codecov](https://codecov.io/gh/mfvanek/pg-index-health/branch/master/graph/badge.svg)](https://codecov.io/gh/mfvanek/pg-index-health)\r\n\r\n[![Bugs](https://sonarcloud.io/api/project_badges/measure?project=mfvanek_pg-index-health\u0026metric=bugs)](https://sonarcloud.io/summary/new_code?id=mfvanek_pg-index-health)\r\n[![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=mfvanek_pg-index-health\u0026metric=vulnerabilities)](https://sonarcloud.io/summary/new_code?id=mfvanek_pg-index-health)\r\n[![Code Smells](https://sonarcloud.io/api/project_badges/measure?project=mfvanek_pg-index-health\u0026metric=code_smells)](https://sonarcloud.io/summary/new_code?id=mfvanek_pg-index-health)\r\n[![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=mfvanek_pg-index-health\u0026metric=ncloc)](https://sonarcloud.io/summary/new_code?id=mfvanek_pg-index-health)\r\n[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=mfvanek_pg-index-health\u0026metric=coverage)](https://sonarcloud.io/summary/new_code?id=mfvanek_pg-index-health)\r\n\r\n[![Mutation testing badge](https://img.shields.io/endpoint?style=flat\u0026url=https%3A%2F%2Fbadge-api.stryker-mutator.io%2Fgithub.com%2Fmfvanek%2Fpg-index-health%2Fmaster)](https://dashboard.stryker-mutator.io/reports/github.com/mfvanek/pg-index-health/master)\r\n\r\n## Supported PostgreSQL versions\r\n\r\n[![PostgreSQL 13](https://img.shields.io/badge/PostgreSQL-13-green.svg)](https://www.postgresql.org/about/news/postgresql-13-released-2077/ \"PostgreSQL 13\")\r\n[![PostgreSQL 14](https://img.shields.io/badge/PostgreSQL-14-green.svg)](https://www.postgresql.org/about/news/postgresql-14-released-2318/ \"PostgreSQL 14\")\r\n[![PostgreSQL 15](https://img.shields.io/badge/PostgreSQL-15-green.svg)](https://www.postgresql.org/about/news/postgresql-15-released-2526/ \"PostgreSQL 15\")\r\n[![PostgreSQL 16](https://img.shields.io/badge/PostgreSQL-16-green.svg)](https://www.postgresql.org/about/news/postgresql-16-released-2715/ \"PostgreSQL 16\")\r\n[![PostgreSQL 17](https://img.shields.io/badge/PostgreSQL-17-green.svg)](https://www.postgresql.org/about/news/postgresql-17-released-2936/ \"PostgreSQL 17\")\r\n\r\n### Support for previous versions of PostgreSQL\r\n\r\nCompatibility with PostgreSQL versions **10**, **11** and **12** is no longer guaranteed, but it is very likely.  \r\nWe focus only on the currently maintained versions of PostgreSQL.  \r\nFor more information please see [PostgreSQL Versioning Policy](https://www.postgresql.org/support/versioning/).\r\n\r\n### Supported Java versions\r\n\r\nSupports [Java 11](https://www.java.com/en/) and above  \r\nFor **Java 8** compatible version take a look at release [0.7.0](https://github.com/mfvanek/pg-index-health/releases/tag/v.0.7.0) and lower\r\n\r\n## Available checks\r\n\r\nAll checks can be divided into 2 groups:\r\n\r\n1. Runtime checks (those that make sense to perform only on a production database with real data and statistics).  \r\n   Runtime checks usually [require aggregating data from all nodes in the cluster](https://github.com/mfvanek/pg-index-health/blob/3e9a63cc2a04799f3e97c9bec9b684ababca8db7/pg-index-health-core/src/main/java/io/github/mfvanek/pg/core/checks/common/Diagnostic.java#L162).\r\n   This necessitated creating [our own abstraction over the database connection](https://github.com/mfvanek/pg-index-health/blob/3e9a63cc2a04799f3e97c9bec9b684ababca8db7/pg-index-health-jdbc-connection/src/main/java/io/github/mfvanek/pg/connection/HighAvailabilityPgConnection.java#L22).\r\n2. Static checks (those can be run in tests on an empty database).  \r\n   All static checks can be performed at runtime as well.\r\n\r\n**pg-index-health** allows you to detect the following problems:\r\n\r\n| №  | Description                                                                                                                        | Type               | Supports partitioning                                         | SQL query                                                                                                         |\r\n|----|------------------------------------------------------------------------------------------------------------------------------------|--------------------|---------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------|\r\n| 1  | Invalid (broken) indexes                                                                                                           | **runtime**/static | yes                                                           | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/invalid_indexes.sql)                         |\r\n| 1  | Duplicated (completely identical) indexes                                                                                          | static             | yes                                                           | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/duplicated_indexes.sql)                      |\r\n| 3  | Intersected (partially identical) indexes                                                                                          | static             | yes                                                           | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/intersected_indexes.sql)                     |\r\n| 4  | Unused indexes                                                                                                                     | **runtime**        | yes                                                           | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/unused_indexes.sql)                          |\r\n| 5  | Foreign keys without associated indexes                                                                                            | static             | yes                                                           | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/foreign_keys_without_index.sql)              |\r\n| 6  | Indexes with null values                                                                                                           | static             | yes                                                           | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/indexes_with_null_values.sql)                |\r\n| 7  | Tables with missing indexes                                                                                                        | **runtime**        | yes                                                           | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/tables_with_missing_indexes.sql)             |\r\n| 8  | Tables without primary key                                                                                                         | static             | yes                                                           | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/tables_without_primary_key.sql)              |\r\n| 9  | Indexes [bloat](https://www.percona.com/blog/2018/08/06/basic-understanding-bloat-vacuum-postgresql-mvcc/)                         | **runtime**        | [no](https://github.com/mfvanek/pg-index-health/issues/589)   | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/bloated_indexes.sql)                         |\r\n| 10 | Tables [bloat](https://www.percona.com/blog/2018/08/06/basic-understanding-bloat-vacuum-postgresql-mvcc/)                          | **runtime**        | yes                                                           | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/bloated_tables.sql)                          |\r\n| 11 | Tables without [description](https://www.postgresql.org/docs/current/sql-comment.html)                                             | static             | yes                                                           | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/tables_without_description.sql)              |\r\n| 12 | Columns without [description](https://www.postgresql.org/docs/current/sql-comment.html)                                            | static             | yes                                                           | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/columns_without_description.sql)             |\r\n| 13 | Columns with [json](https://www.postgresql.org/docs/current/datatype-json.html) type                                               | static             | yes                                                           | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/columns_with_json_type.sql)                  |\r\n| 14 | Columns of [serial types](https://www.postgresql.org/docs/current/datatype-numeric.html#DATATYPE-SERIAL) that are not primary keys | static             | yes                                                           | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/columns_with_serial_types.sql)               |\r\n| 15 | Functions without [description](https://www.postgresql.org/docs/current/sql-comment.html)                                          | static             | not applicable                                                | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/functions_without_description.sql)           |\r\n| 16 | Indexes [with boolean](https://habr.com/ru/companies/tensor/articles/488104/)                                                      | static             | yes                                                           | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/indexes_with_boolean.sql)                    |\r\n| 17 | Tables with [not valid constraints](https://habr.com/ru/articles/800121/)                                                          | **runtime**/static | yes                                                           | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/not_valid_constraints.sql)                   |\r\n| 18 | B-tree indexes [on array columns](https://habr.com/ru/articles/800121/)                                                            | static             | yes                                                           | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/btree_indexes_on_array_columns.sql)          |\r\n| 19 | [Sequence overflow](https://habr.com/ru/articles/800121/)                                                                          | **runtime**        | not applicable                                                | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/sequence_overflow.sql)                       |\r\n| 20 | Primary keys with [serial types](https://wiki.postgresql.org/wiki/Don't_Do_This#Don.27t_use_serial)                                | static             | yes                                                           | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/primary_keys_with_serial_types.sql)          |\r\n| 21 | Duplicated ([completely identical](https://habr.com/ru/articles/803841/)) foreign keys                                             | static             | yes                                                           | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/duplicated_foreign_keys.sql)                 |\r\n| 22 | Intersected ([partially identical](https://habr.com/ru/articles/803841/)) foreign keys                                             | static             | yes                                                           | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/intersected_foreign_keys.sql)                |\r\n| 23 | Possible object name overflow (identifiers with maximum length)                                                                    | static             | yes                                                           | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/possible_object_name_overflow.sql)           |\r\n| 24 | Tables not linked to other tables                                                                                                  | static             | yes                                                           | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/tables_not_linked_to_others.sql)             |\r\n| 25 | Foreign keys [with unmatched column type](https://habr.com/ru/articles/803841/)                                                    | static             | yes                                                           | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/foreign_keys_with_unmatched_column_type.sql) |\r\n| 26 | Tables with zero or one column                                                                                                     | static             | yes                                                           | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/tables_with_zero_or_one_column.sql)          |\r\n| 27 | Objects whose names do not follow naming convention                                                                                | static             | yes                                                           | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/objects_not_following_naming_convention.sql) |\r\n\r\nFor raw sql queries see [pg-index-health-sql](https://github.com/mfvanek/pg-index-health-sql) project.\r\n\r\n## How does it work?\r\n\r\n### Static checks\r\n\r\nStatic checks are based on [information schema](https://www.postgresql.org/docs/current/information-schema.html)/[system catalogs](https://www.postgresql.org/docs/current/catalogs.html).\r\nThey work with finite database state (after all migrations are applied).\r\n\r\n### Runtime checks\r\n\r\n**pg_index_health** utilizes [the Cumulative Statistics System](https://www.postgresql.org/docs/current/monitoring-stats.html) \r\n(formerly known as [PostgreSQL's statistics collector](https://www.postgresql.org/docs/14/monitoring-stats.html)).\r\n\r\nYou can call `pg_stat_reset()` on each host to reset all statistics counters for the current database to zero\r\nbut the best way to do it is to use [DatabaseManagement::resetStatistics()](https://github.com/mfvanek/pg-index-health/blob/3e9a63cc2a04799f3e97c9bec9b684ababca8db7/pg-index-health/src/main/java/io/github/mfvanek/pg/health/checks/management/DatabaseManagement.java#L33) method.\r\n\r\n## Installation\r\n\r\nUsing Gradle:\r\n```groovy\r\nimplementation 'io.github.mfvanek:pg-index-health:0.14.5'\r\n```\r\n\r\n\u003cdetails\u003e\r\n\u003csummary\u003ewith Kotlin DSL\u003c/summary\u003e\r\n\r\n```kotlin\r\nimplementation(\"io.github.mfvanek:pg-index-health:0.14.5\")\r\n```\r\n\u003c/details\u003e\r\n\r\nUsing Maven:\r\n```xml\r\n\u003cdependency\u003e\r\n  \u003cgroupId\u003eio.github.mfvanek\u003c/groupId\u003e\r\n  \u003cartifactId\u003epg-index-health\u003c/artifactId\u003e\r\n  \u003cversion\u003e0.14.5\u003c/version\u003e\r\n\u003c/dependency\u003e\r\n```\r\n\r\n## Articles and publications\r\n\r\n### In English\r\n\r\n* [pg-index-health – a static analysis tool for you PostgreSQL database](https://dev.to/mfvanek/pg-index-health-a-static-analysis-tool-for-you-postgresql-database-2no5)\r\n\r\n### In Russian\r\n\r\n* [pg-index-health – static analysis of the structure of PostgreSQL databases](https://habr.com/ru/articles/871546/)\r\n* [Index health in PostgreSQL through the eyes of a Java developer](https://habr.com/ru/post/490824/)\r\n* [DBA: finding useless indexes](https://habr.com/ru/companies/tensor/articles/488104/)\r\n* [The series of articles \"Static analysis of the database structure\"](https://habr.com/ru/articles/800121/)\r\n\r\n## How to use\r\n\r\nThere are three main scenarios of using **pg-index-health** in your projects:\r\n* unit\\functional testing (see **standard test** in section below);\r\n* collecting indexes health data and monitoring bloat;\r\n* analysis of database configuration.\r\n\r\nAll these cases are covered with examples in the [pg-index-health-demo](https://github.com/mfvanek/pg-index-health-demo) project.\r\n\r\n## Integration with Spring Boot\r\n\r\nThere is a Spring Boot starter [pg-index-health-test-starter](spring-boot-integration%2Fpg-index-health-test-starter)\r\nfor unit/integration testing as well.  \r\nMore examples you can find in [pg-index-health-demo](https://github.com/mfvanek/pg-index-health-demo) project.\r\n\r\n### Starter installation\r\n\r\nUsing Gradle:\r\n\r\n```groovy\r\ntestImplementation 'io.github.mfvanek:pg-index-health-test-starter:0.14.5'\r\n```\r\n\r\n\u003cdetails\u003e\r\n\u003csummary\u003ewith Kotlin DSL\u003c/summary\u003e\r\n\r\n```kotlin\r\ntestImplementation(\"io.github.mfvanek:pg-index-health-test-starter:0.14.5\")\r\n```\r\n\r\n\u003c/details\u003e\r\n\r\nUsing Maven:\r\n\r\n```xml\r\n\u003cdependency\u003e\r\n    \u003cgroupId\u003eio.github.mfvanek\u003c/groupId\u003e\r\n    \u003cartifactId\u003epg-index-health-test-starter\u003c/artifactId\u003e\r\n    \u003cversion\u003e0.14.5\u003c/version\u003e\r\n    \u003cscope\u003etest\u003c/scope\u003e\r\n\u003c/dependency\u003e\r\n```\r\n\r\n### Standard test\r\n\r\nAdd a standard test to your project as shown below. Ideally, all checks should work and return an empty result.\r\n\r\n```java\r\nimport io.github.mfvanek.pg.core.checks.common.DatabaseCheckOnHost;\r\nimport io.github.mfvanek.pg.core.checks.common.Diagnostic;\r\nimport io.github.mfvanek.pg.model.dbobject.DbObject;\r\nimport org.junit.jupiter.api.Test;\r\nimport org.springframework.beans.factory.annotation.Autowired;\r\nimport org.springframework.boot.test.context.SpringBootTest;\r\nimport org.springframework.test.context.ActiveProfiles;\r\n\r\nimport java.util.List;\r\n\r\nimport static org.assertj.core.api.Assertions.assertThat;\r\n\r\n@SpringBootTest\r\n@ActiveProfiles(\"test\")\r\nclass DatabaseStructureStaticAnalysisTest {\r\n\r\n    @Autowired\r\n    private List\u003cDatabaseCheckOnHost\u003c? extends DbObject\u003e\u003e checks;\r\n\r\n    @Test\r\n    void checksShouldWork() {\r\n        assertThat(checks)\r\n            .hasSameSizeAs(Diagnostic.values());\r\n\r\n        checks.stream()\r\n            .filter(DatabaseCheckOnHost::isStatic)\r\n            .forEach(c -\u003e\r\n                assertThat(c.check())\r\n                    .as(c.getDiagnostic().name())\r\n                    .isEmpty());\r\n    }\r\n}\r\n```\r\n\r\n### Spring Boot compatibility\r\n\r\n| Spring Boot | Min JDK | pg-index-health-test-starter |\r\n|-------------|---------|------------------------------|\r\n| 2.4.x       | 8       | 0.3.x — 0.4.x                |\r\n| 2.5.x       | 8       | 0.5.x — 0.6.x                |\r\n| 2.6.x       | 8       | 0.7.x                        |\r\n| 2.7.x       | 11      | 0.8.x — 0.14.x               |\r\n\r\n#### Spring Boot 3 compatibility\r\n\r\n* Starting from [0.9.0.1](https://github.com/mfvanek/pg-index-health-test-starter/releases/tag/v.0.9.0.1)\r\n  added support for [Spring Boot 3.0](https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Migration-Guide#auto-configuration-files)\r\n* Starting from [0.10.2](https://github.com/mfvanek/pg-index-health-test-starter/releases/tag/v.0.10.2)\r\n  added support for [Spring Boot 3.2](https://github.com/spring-projects/spring-framework/wiki/Upgrading-to-Spring-Framework-6.x#parameter-name-retention)\r\n\r\n## Questions, issues, feature requests and contributions\r\n\r\n* If you have any question or a problem with the library, please [file an issue](https://github.com/mfvanek/pg-index-health/issues).\r\n* Contributions are always welcome! Please see [contributing guide](CONTRIBUTING.md) for more details.\r\n* We utilize [Testcontainers](https://www.testcontainers.org/) for testing **pg-index-health**. \r\nSo you need to have [Docker](https://www.docker.com/) installed on your machine.\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmfvanek%2Fpg-index-health","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmfvanek%2Fpg-index-health","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmfvanek%2Fpg-index-health/lists"}