{"id":15038559,"url":"https://github.com/hypopg/hypopg","last_synced_at":"2025-05-14T10:09:38.726Z","repository":{"id":33655734,"uuid":"37308208","full_name":"HypoPG/hypopg","owner":"HypoPG","description":"Hypothetical Indexes for PostgreSQL","archived":false,"fork":false,"pushed_at":"2025-03-22T06:15:54.000Z","size":844,"stargazers_count":1459,"open_issues_count":2,"forks_count":61,"subscribers_count":28,"default_branch":"REL1_STABLE","last_synced_at":"2025-03-28T15:02:53.451Z","etag":null,"topics":["c","database","extension","hypothetical-indexes","index","indexing","postgresql"],"latest_commit_sha":null,"homepage":"https://hypopg.readthedocs.io","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/HypoPG.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"docs/contributing.rst","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-06-12T07:25:50.000Z","updated_at":"2025-03-28T11:54:06.000Z","dependencies_parsed_at":"2023-11-29T06:30:58.139Z","dependency_job_id":"99cf5371-abff-4714-9f47-e64b48a20efa","html_url":"https://github.com/HypoPG/hypopg","commit_stats":{"total_commits":300,"total_committers":16,"mean_commits":18.75,"dds":0.06666666666666665,"last_synced_commit":"5fdf0ef8c0487714fb4a7d32ede662dd2a245e3e"},"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HypoPG%2Fhypopg","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HypoPG%2Fhypopg/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HypoPG%2Fhypopg/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HypoPG%2Fhypopg/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/HypoPG","download_url":"https://codeload.github.com/HypoPG/hypopg/tar.gz/refs/heads/REL1_STABLE","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246049630,"owners_count":20715511,"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":["c","database","extension","hypothetical-indexes","index","indexing","postgresql"],"created_at":"2024-09-24T20:38:54.002Z","updated_at":"2025-03-28T15:03:56.163Z","avatar_url":"https://github.com/HypoPG.png","language":"C","readme":"HypoPG\n=======\n\nHypoPG is a PostgreSQL extension adding support for hypothetical indexes.\n\nA hypothetical -- or virtual -- index is an index that doesn't really exist, and\nthus doesn't cost CPU, disk or any resource to create.  They're useful to know\nif specific indexes can increase performance for problematic queries, since\nyou can know if PostgreSQL will use these indexes or not without having to\nspend resources to create them.\n\nFor more thorough information, please consult the [official\ndocumentation](https://hypopg.readthedocs.io).\n\nFor other general information, you can also consult [this blog\npost](https://rjuju.github.io/postgresql/2015/07/02/how-about-hypothetical-indexes.html).\n\nInstallation\n------------\n\n- Compatible with PostgreSQL 9.2 and above\n- Needs PostgreSQL header files\n- Decompress the tarball\n- `sudo make install`\n- In every needed database: `CREATE EXTENSION hypopg;`\n\n\nUpdating the extension\n----------------------\n\nNote that hypopg doesn't provide extension upgrade scripts, as there's no\ndata saved in any of the objects created.  Therefore, you need to first drop\nthe extension then create it again to get the new version.\n\nUsage\n-----\n\nNOTE: The hypothetical indexes are contained in a single backend. Therefore,\nif you add multiple hypothetical indexes, concurrent connections doing\n`EXPLAIN` won't be bothered by your hypothetical indexes.\n\nAssuming a simple test case:\n\n    rjuju=# CREATE TABLE hypo AS SELECT id, 'line ' || id AS val FROM generate_series(1,10000) id;\n    rjuju=# EXPLAIN SELECT * FROM hypo WHERE id = 1;\n                          QUERY PLAN\n    -------------------------------------------------------\n     Seq Scan on hypo  (cost=0.00..180.00 rows=1 width=13)\n       Filter: (id = 1)\n    (2 rows)\n\n\nThe easiest way to create an hypothetical index is to use the\n`hypopg_create_index` functions with a regular `CREATE INDEX` statement as arg.\n\nFor instance:\n\n    rjuju=# SELECT * FROM hypopg_create_index('CREATE INDEX ON hypo (id)');\n\nNOTE: Some information from the `CREATE INDEX` statement will be ignored, such as\nthe index name if provided. Some of the ignored information will be handled in\na future release.\n\nYou can check the available hypothetical indexes in your own backend:\n\n    rjuju=# SELECT * FROM hypopg_list_indexes ;\n     indexrelid |          index_name           | schema_name | table_name | am_name \n    ------------+-------------------------------+-------------+------------+---------\n          50573 | \u003c50573\u003ebtree_hypo_id          | public      | hypo       | btree\n\nIf the `CREATE INDEX` command you want to use also needs quoting, using the\n[dollar quoting\nsyntax](https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-DOLLAR-QUOTING)\nis recommended.  For instance:\n\n    rjuju=# SELECT * FROM hypopg_create_index($$CREATE INDEX ON hypo (id) WHERE val = 'line 1'$$);\n\nIf you need more technical information on the hypothetical indexes, the\n`hypopg()` function will return the hypothetical indexes in a similar way as\n`pg_index` system catalog.\n\nAnd now, let's see if your previous `EXPLAIN` statement would use such an index:\n\n    rjuju=# EXPLAIN SELECT * FROM hypo WHERE id = 1;\n                                         QUERY PLAN\n    ------------------------------------------------------------------------------------\n     Index Scan using \u003c41072\u003ehypo_btree_hypo_id on hypo  (cost=0.29..8.30 rows=1 width=13)\n       Index Cond: (id = 1)\n    (2 rows)\n\n\nOf course, only `EXPLAIN` without `ANALYZE` will use hypothetical indexes:\n\n    rjuju=# EXPLAIN ANALYZE SELECT * FROM hypo WHERE id = 1;\n                                               QUERY PLAN\n    -------------------------------------------------------------------------------------------------\n     Seq Scan on hypo  (cost=0.00..180.00 rows=1 width=13) (actual time=0.036..6.072 rows=1 loops=1)\n       Filter: (id = 1)\n       Rows Removed by Filter: 9999\n     Planning time: 0.109 ms\n     Execution time: 6.113 ms\n    (5 rows)\n\nTo remove your backend's hypothetical indexes, you can use the function\n`hypopg_drop_index(indexrelid)` with the OID that the `hypopg_list_indexes`\nview returns and call `hypopg_reset()` to remove all at once, or just close\nyour current connection.\n\nContinuing with the above case, you can `hide existing indexes`,\nbut should be use `hypopg_reset()` to clear the previous effects of other indexes at first.\n\nCreate two real indexes and run `EXPLAIN`:\n\n    rjuju=# SELECT hypopg_reset();\n    rjuju=# CREATE INDEX ON hypo(id);\n    rjuju=# CREATE INDEX ON hypo(id, val);\n    rjuju=# EXPLAIN SELECT * FROM hypo WHERE id = 1;\n                                        QUERY PLAN\n    ----------------------------------------------------------------------------------\n    Index Only Scan using hypo_id_val_idx on hypo  (cost=0.29..8.30 rows=1 width=13)\n    Index Cond: (id = 1)\n    (2 rows)\n\nThe query plan is using the `hypo_id_val_idx` index. Use `hypopg_hide_index(oid)` to hide one of the indexes:\n\n    rjuju=# SELECT hypopg_hide_index('hypo_id_val_idx'::REGCLASS);\n    rjuju=# EXPLAIN SELECT * FROM hypo WHERE id = 1;\n                                QUERY PLAN\n    -------------------------------------------------------------------------\n    Index Scan using hypo_id_idx on hypo  (cost=0.29..8.30 rows=1 width=13)\n    Index Cond: (id = 1)\n    (2 rows)\n\nThe query plan is using the other index `hypo_id_idx` now. Use `hypopg_hide_index(oid)` to hide it:\n\n    rjuju=# SELECT hypopg_hide_index('hypo_id_idx'::REGCLASS);\n    rjuju=# EXPLAIN SELECT * FROM hypo WHERE id = 1;\n                        QUERY PLAN\n    -------------------------------------------------------\n    Seq Scan on hypo  (cost=0.00..180.00 rows=1 width=13)\n    Filter: (id = 1)\n    (2 rows)\n\nAnd now the query plan changes back to `Seq Scan`. Use `hypopg_unhide_index(oid)` to restore index:\n\n    rjuju=# SELECT hypopg_unhide_index('hypo_id_idx'::regclass);\n    rjuju=# EXPLAIN SELECT * FROM hypo WHERE id = 1;\n                                QUERY PLAN\n    -------------------------------------------------------------------------\n    Index Scan using hypo_id_idx on hypo  (cost=0.29..8.30 rows=1 width=13)\n    Index Cond: (id = 1)\n    (2 rows)\n\nOf course, you can also hide hypothetical indexes:\n\n    rjuju=# SELECT hypopg_create_index('CREATE INDEX ON hypo(id)');\n    rjuju=# EXPLAIN SELECT * FROM hypo WHERE id = 1;\n                                        QUERY PLAN\n    ------------------------------------------------------------------------------------\n    Index Scan using \"\u003c12659\u003ebtree_hypo_id\" on hypo  (cost=0.04..8.05 rows=1 width=13)\n    Index Cond: (id = 1)\n    (2 rows)\n\n    rjuju=# SELECT hypopg_hide_index(12659);\n    rjuju=# EXPLAIN SELECT * FROM hypo WHERE id = 1;\n                        QUERY PLAN\n    -------------------------------------------------------\n    Seq Scan on hypo  (cost=0.00..180.00 rows=1 width=13)\n    Filter: (id = 1)\n    (2 rows)\n\nYou can check which indexes are hidden using `hypopg_hidden_indexes()` or the `hypopg_hidden_indexes` view:\n\n    rjuju=# SELECT * FROM hypopg_hidden_indexes();\n    indexid\n    ---------\n    526604\n    526603\n    12659\n    (3 rows)\n\n    rjuju=# SELECT * FROM hypopg_hidden_indexes;\n     indexrelid |      index_name      | schema_name | table_name | am_name | is_hypo\n    ------------+----------------------+-------------+------------+---------+---------\n          12659 | \u003c12659\u003ebtree_hypo_id | public      | hypo       | btree   | t\n         526603 | hypo_id_idx          | public      | hypo       | btree   | f\n         526604 | hypo_id_val_idx      | public      | hypo       | btree   | f\n    (3 rows)\n\nTo restore all existing indexes, you can use the function `hypopg_unhide_all_indexes()`.\nNote that the functionality to hide existing indexes only applies to the EXPLAIN command in the current session\nand will not affect other sessions.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhypopg%2Fhypopg","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhypopg%2Fhypopg","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhypopg%2Fhypopg/lists"}