{"id":16066,"date":"2022-08-29T13:01:37","date_gmt":"2022-08-29T20:01:37","guid":{"rendered":"https:\/\/coderpad.io\/?p=16066"},"modified":"2023-06-05T14:12:30","modified_gmt":"2023-06-05T21:12:30","slug":"postgresql-system-catalogs-metadata","status":"publish","type":"post","link":"https:\/\/coderpad.io\/blog\/development\/postgresql-system-catalogs-metadata\/","title":{"rendered":"How to Get Metadata from PostgreSQL System Catalogs"},"content":{"rendered":"\n<p><a target=\"_blank\" href=\"https:\/\/www.postgresql.org\/\" rel=\"noreferrer noopener\">PostgreSQL<\/a>&nbsp;is a well-known database engine that allows you to write performant SQL queries.<\/p>\n\n\n\n<p>In this tutorial, you&#8217;ll learn about the internal building blocks of PostgreSQL \u2013 also known as&nbsp;<em>system catalogs<\/em>&nbsp;\u2013 to see how the PostgreSQL backend is structured.&nbsp;<\/p>\n\n\n\n<p>This tutorial aims to give you insights into how PostgreSQL system catalogs can help you manage your schemas, databases, tables, and even table columns.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>What is a PostgreSQL system catalog?<\/strong><\/h2>\n\n\n\n<p>When you set up PostgreSQL in your machine, you spin up a PostgreSQL&nbsp;<em>cluster<\/em>, a server that hosts databases.<\/p>\n\n\n\n<p>This cluster has a set of catalogs. Each&nbsp;<em>catalog<\/em>&nbsp;is a collection of schemas, and each&nbsp;<em>schema<\/em>&nbsp;has a set of tables.<\/p>\n\n\n\n<p><strong>System catalogs<\/strong>&nbsp;are where a database management system stores schema metadata, such as information about databases, tables, and columns.&nbsp;<\/p>\n\n\n\n<p>These catalogs are regular tables where you can manipulate data as you do with other tables. You can insert new rows, update values, add columns \u2013 or potentially mess up your system. So you shouldn&#8217;t change the system catalogs unless you&nbsp;<em>really&nbsp;<\/em>know what you&#8217;re doing.<\/p>\n\n\n\n<p>A few system catalogs are shared across all databases in the PostgreSQL cluster. However, most system catalogs are database-specific.<\/p>\n\n\n\n<p>Each system catalog name starts with &#8220;pg_&#8221;. PostgreSQL has some funny naming conventions for the column names of system catalogs. A high percentage of columns \u2013 if not all \u2013 have a prefix of a combination of three letters of the name after &#8220;pg_&#8221;. For example, the <code>pg_database<\/code> has columns starting with &#8220;dat&#8221;, like&nbsp;<em>datname,&nbsp;<\/em>which is the database name column.<\/p>\n\n\n\n<p>A couple more examples are:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><code>pg_proc<\/code>, which has columns that start with &#8220;pro&#8221;.<\/li><li><code>pg_namespace<\/code>, which has columns that begin with &#8220;nsp&#8221;.<\/li><\/ul>\n\n\n\n<p>Another interesting example is <code>pg_class<\/code>, which has columns that start with &#8220;rel&#8221;. This is because the <code>pg_class<\/code> catalog stores all information about tables and other objects that have columns. These kinds of objects are referred to as &#8220;relations&#8221;.<\/p>\n\n\n\n<p>A typical example is a <code>pg_constraint<\/code> catalog, which stores primary, unique, and foreign keys and table constraints. Each column starts with &#8220;con&#8221; except for the <code>oid<\/code> column, which is the row identifier.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Getting started: Prerequisities<\/strong><\/h2>\n\n\n\n<p>Following this tutorial, you&#8217;ll need to write SQL commands in your desired SQL client. You can also use&nbsp;<a href=\"https:\/\/app.coderpad.io\/sandbox?language=postgresql\" target=\"_blank\" rel=\"noreferrer noopener\">CoderPad&#8217;s sandbox<\/a>, which uses PostgreSQL 12.<\/p>\n\n\n\n<p>One pro tip on CoderPad sandbox is to head over to the right terminal and run this to prettify the output of the SQL command:<\/p>\n\n\n\n<p><code>coderpad=# \\x<\/code><\/p>\n\n\n\n<p>This is useful, especially if the record length is long. For example, this is before running <code>\\x<\/code>:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><a href=\"https:\/\/d2h1bfu6zrdxog.cloudfront.net\/wp-content\/uploads\/2022\/08\/image-65.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/d2h1bfu6zrdxog.cloudfront.net\/wp-content\/uploads\/2022\/08\/image-65.png\" alt=\"SQL query of select * from pg_class limit 1;. screen is hard to read.\" class=\"wp-image-16073\" width=\"514\" height=\"369\" srcset=\"https:\/\/coderpad.io\/wp-content\/uploads\/2022\/08\/image-65.png 685w, https:\/\/coderpad.io\/wp-content\/uploads\/2022\/08\/image-65-300x215.png 300w\" sizes=\"auto, (max-width: 514px) 100vw, 514px\" \/><\/a><\/figure>\n<\/div>\n\n\n<p>And now, to prettify that mess, run <code>\\x<\/code> on the terminal for expanded formatting for each record:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><a href=\"https:\/\/d2h1bfu6zrdxog.cloudfront.net\/wp-content\/uploads\/2022\/08\/image-66.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/d2h1bfu6zrdxog.cloudfront.net\/wp-content\/uploads\/2022\/08\/image-66.png\" alt=\"SQL query of select * from pg_class limit 1;, but \\x is run first. much easier to read.\" class=\"wp-image-16074\" width=\"378\" height=\"389\" srcset=\"https:\/\/coderpad.io\/wp-content\/uploads\/2022\/08\/image-66.png 504w, https:\/\/coderpad.io\/wp-content\/uploads\/2022\/08\/image-66-292x300.png 292w\" sizes=\"auto, (max-width: 378px) 100vw, 378px\" \/><\/a><\/figure>\n<\/div>\n\n\n<h2 class=\"wp-block-heading\"><strong>Why getting metadata is useful<\/strong><\/h2>\n\n\n\n<p>Getting PostgreSQL metadata can help you have information about databases, tables, schema, indexes, columns, functions, and even size information.<\/p>\n\n\n\n<p>To name a few use cases, you can do the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Know who the database owner is<\/li><li>Extract the number of transactions committed to the database<\/li><li>List all tables in the PostgreSQL cluster<\/li><li>Investigate the number of full scans, index scans, etc.<\/li><li>Retrieve all schemas in your cluster<\/li><li>Be informed of the tables that have no indexes so you can fix performance issues<\/li><li>Investigate the data types of columns that have problems in your tables<\/li><li>List functions based on their inputs<\/li><li>Know the size of tables, databases, indexes, etc.<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>How to get database metadata<\/strong><\/h2>\n\n\n\n<p>In this section, I&#8217;ll talk about how to get database metadata, get the name of the database owner, and extract statistical information about the database, like the number of transactions.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Using pg_database<\/strong><\/h3>\n\n\n\n<p>The <code>pg_database<\/code> catalog stores information about Postgres databases available in your cluster. Whenever you run the SQL command <code>CREATE DATABASE<\/code>, a new row is inserted into the <code>pg_database<\/code> catalog. This row has metadata related to that particular database.<\/p>\n\n\n\n<p>This <code>pg_database<\/code> catalog is system-wide, which means it&#8217;s shared across all databases in the cluster.<\/p>\n\n\n\n<p>A query on <code>pg_database<\/code> would look something like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">SELECT datdba\nFROM\u00a0pg_database\nWHERE\u00a0datname = <span class=\"hljs-string\">'coderpad'<\/span>;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This query would get you information about the&nbsp;<em>coderpad<\/em>&nbsp;database, like the database owner. In this case, it returns the string <code>10<\/code>, which references the <code>OID<\/code> in the <code>pg_authid<\/code> catalog.<\/p>\n\n\n\n<p>To get the&nbsp;<em>coderpad<\/em>&nbsp;owner who initially created the database, you&#8217;d use this query:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php shcb-wrap-lines\">SELECT\u00a0a.rolname\u00a0<span class=\"hljs-keyword\">AS<\/span>\u00a0<span class=\"hljs-string\">\"Owner\"<\/span>\nFROM\u00a0pg_database d\nJOIN\u00a0pg_authid a\u00a0ON\u00a0a.oid = d.datdba\nWHERE\u00a0datname = <span class=\"hljs-string\">'coderpad'<\/span>;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\"><strong>Using pg_stat_database<\/strong><\/h3>\n\n\n\n<p>The <code>pg_stat_database<\/code> catalog stores statistical information about the database. This catalog is database-specific.<\/p>\n\n\n\n<p>Here&#8217;s an example query using <code>pg_stat_database<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">SELECT\u00a0xact_commit, xact_rollback\nFROM\u00a0pg_stat_database\nWHERE\u00a0datname = <span class=\"hljs-string\">'coderpad'<\/span>;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This query helps us analyze database transaction metadata. The <code>xact_commit<\/code> attribute shows how many transactions are committed in this database, while the <code>xact_rollback<\/code> attribute indicates how many transactions have been rolled back (errored) in this database.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>How to retrieve table metadata<\/strong><\/h2>\n\n\n\n<p>In this section, I&#8217;ll talk about how to get table metadata, list all tables in the cluster, and retrieve statistical information and activity about tables, like the number of different scans.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Using pg_class<\/strong><\/h3>\n\n\n\n<p>As mentioned earlier, the <code>pg_class<\/code> catalog stores relations, such as tables, indexes, and views.<\/p>\n\n\n\n<p>To list all ordinary tables in the cluster, run the following query:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">SELECT\u00a0*\nFROM\u00a0pg_class\nWHERE\u00a0relkind = <span class=\"hljs-string\">'r'<\/span>;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The <code>r<\/code> string value in the <code>relkind<\/code> attribute points to the ordinary table.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Using pg_stat_user_tables<\/strong><\/h3>\n\n\n\n<p>The <code>pg_stat_user_tables<\/code> catalog stores stats and activity about tables. For example, take this query:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">SELECT\u00a0seq_scan, idx_scan\nFROM\u00a0pg_stat_user_tables\nWHERE\u00a0relname = <span class=\"hljs-string\">'projects'<\/span>;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>It gets the number of sequential scans and the number of index scans initiated on the&nbsp;<em>projects<\/em>&nbsp;table. Sequential scans are full scans where each row in the table is scanned. In most cases, sequential scans are slow, especially when you retrieve a minimal number from a big table (aka, the selectivity ratio is low). In contrast, index scans do not scan the whole tables and instead scan the tree data structure created when there is an index to that table.<\/p>\n\n\n\n<p>This catalog is a database-specific query, so the&nbsp;<em>project&#8217;s<\/em>&nbsp;relation resides on the&nbsp;<em>coderpad&nbsp;<\/em>database.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>How to get schema metadata<\/strong><\/h2>\n\n\n\n<p>In this section, I&#8217;ll talk about how to get schema metadata and get all schema names in your PostgreSQL cluster.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Using pg_namespace<\/strong><\/h3>\n\n\n\n<p>The <code>pg_namespace<\/code> catalog stores namespaces. Per the&nbsp;<a target=\"_blank\" href=\"https:\/\/www.postgresql.org\/docs\/current\/catalog-pg-namespace.html\" rel=\"noreferrer noopener\">PostgreSQL documentation<\/a>, a namespace is the structure underlying SQL schemas. That means whenever you run the <code>CREATE SCHEMA<\/code> command, a new record is created under <code>pg_namespace<\/code>. Each namespace can have a separate collection of relations, types, etc., without name conflicts.<\/p>\n\n\n\n<p>To list all schema names, run the following query:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs shcb-wrap-lines\">SELECT\u00a0nspname\nFROM\u00a0pg_namespace;<\/code><\/span><\/pre>\n\n\n<h2 class=\"wp-block-heading\"><strong>How to get indexes metadata<\/strong><\/h2>\n\n\n\n<p>In this section, I&#8217;ll talk about how to get indexes metadata and tables that don&#8217;t use indexes across the PostgreSQL cluster or on a specific database.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Using pg_index<\/strong><\/h3>\n\n\n\n<p>Part of the information about indexes is stored in the <code>pg_index<\/code> catalog. The rest is mostly in <code>pg_class<\/code>.<\/p>\n\n\n\n<p>To get tables across the system that have no indexes, I have used the following query (which appeared in a&nbsp;<a href=\"https:\/\/www.youtube.com\/watch?v=3Tfcmq2IA6k&amp;ab_channel=DanLangille\" target=\"_blank\" rel=\"noreferrer noopener\">Postgres conference workshop<\/a>):<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php shcb-wrap-lines\">SELECT\u00a0c.oid::regclass c\nFROM\u00a0pg_class c\nWHERE\u00a0relkind = <span class=\"hljs-string\">'r'<\/span>\n<span class=\"hljs-keyword\">AND<\/span>\u00a0NOT\u00a0EXISTS\u00a0(SELECT\u00a0<span class=\"hljs-number\">1<\/span>\u00a0FROM\u00a0pg_index i\u00a0WHERE\u00a0i.indrelid = c.oid);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p><strong>Note<\/strong>: the <code>reg*<\/code> data type is used to format names. In the previous query, I used <code>regclass<\/code> to format the relation&#8217;s name according to the class.<\/p>\n\n\n\n<p>If you want to list all tables that don&#8217;t have indexes except the ones that exist on information schema (This query is based on one introduced in this&nbsp;<a href=\"https:\/\/www.youtube.com\/watch?v=3Tfcmq2IA6k&amp;ab_channel=DanLangille\" target=\"_blank\" rel=\"noreferrer noopener\">Rober Haas workshop<\/a>):<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php shcb-wrap-lines\">SELECT\u00a0c.oid::regclass c\nFROM\u00a0pg_class c\nWHERE\u00a0relkind = <span class=\"hljs-string\">'r'<\/span>\n<span class=\"hljs-keyword\">AND<\/span>\u00a0NOT\u00a0EXISTS\u00a0(SELECT\u00a0<span class=\"hljs-number\">1<\/span>\u00a0FROM\u00a0pg_index i\u00a0WHERE\u00a0i.indrelid = c.oid)\n<span class=\"hljs-keyword\">AND<\/span>\u00a0c.relnamespace\u00a0NOT\u00a0IN\u00a0(<span class=\"hljs-number\">13127<\/span>);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\"><strong>Using pg_stat_user_tables.idx_scan<\/strong><\/h3>\n\n\n\n<p>The database-specific query equivalent to the previous system-wide one is:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php shcb-wrap-lines\">SELECT\u00a0relname\nFROM\u00a0pg_stat_user_tables\nWHERE\u00a0idx_scan\u00a0IS\u00a0<span class=\"hljs-keyword\">NULL<\/span>;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\"><strong>How to get columns metadata<\/strong><\/h2>\n\n\n\n<p>In this section, I&#8217;ll talk about how to get column metadata and know their data types across the PostgreSQL cluster.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Using pg_attribute<\/strong><\/h3>\n\n\n\n<p>The <code>pg_attribute<\/code> catalog stores information about table columns. Every column in any table has a <code>pg_attribute<\/code> row in the database.<\/p>\n\n\n\n<p>To list the first 50 attribute names with their corresponding data type, run the following query:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-wrap-lines\"><span class=\"hljs-selector-tag\">SELECT<\/span>\u00a0<span class=\"hljs-selector-tag\">attname<\/span>, <span class=\"hljs-selector-tag\">atttypid<\/span><span class=\"hljs-selector-pseudo\">::regtype<\/span>\n<span class=\"hljs-selector-tag\">FROM<\/span>\u00a0<span class=\"hljs-selector-tag\">pg_attribute<\/span>\n<span class=\"hljs-selector-tag\">LIMIT<\/span>\u00a050;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p><strong>Note:<\/strong>&nbsp;The <code>regtype<\/code> data type here is used to format the attribute type id into a data type like <code>name<\/code>, <code>boolean<\/code>, <code>smallint<\/code>, and more.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>How to get functions metadata<\/strong><\/h2>\n\n\n\n<p>In this section, I&#8217;ll talk about how to get function metadata and get specific kinds of functions based on the input across the cluster.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Using pg_proc<\/strong><\/h3>\n\n\n\n<p>To get all PostgreSQL functions that take text, run the following query (introduced in a&nbsp;<a href=\"https:\/\/www.youtube.com\/watch?v=3Tfcmq2IA6k&amp;ab_channel=DanLangille\" target=\"_blank\" rel=\"noreferrer noopener\">PGCon workshop<\/a>):<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php shcb-wrap-lines\">SELECT\u00a0oid::regprocedure\nFROM\u00a0pg_proc\nWHERE\u00a0<span class=\"hljs-string\">'text'<\/span>::regtype =\u00a0ANY(proargtypes);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p><strong>Note:<\/strong>&nbsp;The <code>regprocedure<\/code> data type gets you each function&#8217;s name and argument type, such as <code>starts_with(text, text)<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>How to get size information<\/strong><\/h2>\n\n\n\n<p>In this section, I&#8217;ll discuss how to get size information about tables, databases, indexes, etc.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Table size using pg_table_size()<\/strong><\/h3>\n\n\n\n<p><code>pg_table_size<\/code> is a database object management function that determines the disk space used by the specified table.<\/p>\n\n\n\n<p>Take a look at the following example (mentioned in the&nbsp;<a href=\"https:\/\/www.youtube.com\/watch?v=3Tfcmq2IA6k&amp;ab_channel=DanLangille\" target=\"_blank\" rel=\"noreferrer noopener\">PGCon workshop<\/a>):<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php shcb-wrap-lines\">SELECT\u00a0name, pg_size_pretty(size)\nFROM\u00a0(SELECT\u00a0oid::regclass\u00a0AS\u00a0name, pg_table_size(oid)\u00a0<span class=\"hljs-keyword\">AS<\/span>\u00a0size\n\u00a0 \u00a0 \u00a0\u00a0FROM\u00a0pg_class\u00a0WHERE\u00a0relkind = <span class=\"hljs-string\">'r'<\/span>) x\nORDER\u00a0BY\u00a0size\u00a0DESC;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This query orders the cluster relations sizes in descending order. The <code>pg_size_pretty()<\/code> function makes the size numbers into a human-readable format like in KB, MB, etc., as the default output size is in bytes.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Database size using pg_database_size()<\/strong><\/h3>\n\n\n\n<p>Similarly, the <code>pg_database_size<\/code> is a database function that computes disk space used by the specified database. So the following query (mentioned in the&nbsp;<a href=\"https:\/\/www.youtube.com\/watch?v=3Tfcmq2IA6k&amp;ab_channel=DanLangille\" target=\"_blank\" rel=\"noreferrer noopener\">Robert Haas workshop<\/a>) orders each database in descending order according to the corresponding size:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php shcb-wrap-lines\">SELECT\u00a0datname, pg_size_pretty(size)\nFROM\u00a0(SELECT\u00a0datname, pg_database_size(oid)\u00a0<span class=\"hljs-keyword\">AS<\/span>\u00a0size\n\u00a0 \u00a0 \u00a0\u00a0FROM\u00a0pg_database) x\nORDER\u00a0BY\u00a0size\u00a0DESC;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\"><strong>Indexes size using pg_indexes_size()<\/strong><\/h3>\n\n\n\n<p>The <code>pg_indexes_size()<\/code> is another function that computes disk space used by the specified index.<\/p>\n\n\n\n<p>The following query gets you records of index names ordered by size:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php shcb-wrap-lines\">SELECT\u00a0i.indexrelname, x.indexrelid, pg_size_pretty(size)\nFROM\u00a0(SELECT\u00a0indexrelid, pg_indexes_size(indrelid)\u00a0<span class=\"hljs-keyword\">AS<\/span>\u00a0size\n\u00a0 \u00a0 \u00a0\u00a0FROM\u00a0pg_index) x\nJOIN\u00a0pg_stat_user_indexes i\u00a0ON\u00a0i.indexrelid = x.indexrelid\nORDER\u00a0BY\u00a0size\u00a0DESC;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\"><strong>Why knowing about system catalogs is useful<\/strong><\/h2>\n\n\n\n<p>Getting information about your PostgreSQL database is not that hard if you know how to use system catalogs.&nbsp;<\/p>\n\n\n\n<p>In addition to what we talked about in this article, here are some other things you can do with your new knowledge of system catalogs:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>You can see how PostgreSQL is configured, so you check that <code>pg_ table<\/code> that contains almost all you need.<\/li><li>Have a slow query? Tracking how many sequential scans or indexes are used might solve this performance problem.<\/li><li>If you&#8217;re worried about the disk space of your database, you can now more easily check how big your databases are getting to see which ones may cause issues.<\/li><\/ul>\n\n\n\n<p>The system catalog will know about every SQL query you write. Practicing more with this wonderful feature will help you and your team to investigate performance, disk space, and memory usage in your cluster.<\/p>\n\n\n\n<p><em>I&#8217;m Ezz. I&#8217;m an AWS Certified Machine Learning Specialist and a Data Platform Engineer. I help SaaS companies rank on Google. Check out my <a href=\"https:\/\/ezzeddinabdullah.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">website<\/a> for more.<\/em><\/p>\n\n\n\n<p><a href=\"https:\/\/www.postgresql.org\/\" target=\"_blank\" rel=\"noreferrer noopener\"><\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>System catalogs are an internal building block of PostgreSQL where schema metadata is stored. This article provides insight into a PostgreSQL system catalog and how it can help you drastically improve performance and quickly troubleshoot bugs.<\/p>\n","protected":false},"author":12,"featured_media":16072,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[9],"tags":[],"persona":[29],"blog-programming-language":[67],"keyword-cluster":[],"class_list":["post-16066","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-development"],"acf":[],"_links":{"self":[{"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/posts\/16066","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/users\/12"}],"replies":[{"embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/comments?post=16066"}],"version-history":[{"count":83,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/posts\/16066\/revisions"}],"predecessor-version":[{"id":21545,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/posts\/16066\/revisions\/21545"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/media\/16072"}],"wp:attachment":[{"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/media?parent=16066"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/categories?post=16066"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/tags?post=16066"},{"taxonomy":"persona","embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/persona?post=16066"},{"taxonomy":"blog-programming-language","embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/blog-programming-language?post=16066"},{"taxonomy":"keyword-cluster","embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/keyword-cluster?post=16066"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}