<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Youssef</title>
    <description>The latest articles on DEV Community by Youssef (@yosefahab).</description>
    <link>https://dev.to/yosefahab</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1103100%2F94cee63d-4cb2-47a1-8d2d-fda447738a1b.png</url>
      <title>DEV Community: Youssef</title>
      <link>https://dev.to/yosefahab</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yosefahab"/>
    <language>en</language>
    <item>
      <title>PostgreSQL EXPLAIN command</title>
      <dc:creator>Youssef</dc:creator>
      <pubDate>Thu, 20 Jul 2023 12:03:24 +0000</pubDate>
      <link>https://dev.to/yosefahab/postgresql-explain-command-3dgh</link>
      <guid>https://dev.to/yosefahab/postgresql-explain-command-3dgh</guid>
      <description>&lt;p&gt;The &lt;code&gt;EXPLAIN&lt;/code&gt; command in Postgres is a very useful tool, it gives insights into how Postgres will perform queries, which means it helps us understand and compare queries for optimization purposes. In this post i'll explain how to use &lt;code&gt;EXPLAIN&lt;/code&gt; command. &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fudqn8b0sasrv35f818se.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fudqn8b0sasrv35f818se.gif" alt="Ironic"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Why?
&lt;/h2&gt;

&lt;p&gt;As previously mentioned, the &lt;code&gt;EXPLAIN&lt;/code&gt; command will help us understand and optimize queries, to further understand why this is needed we need to look at SQL.&lt;br&gt;
SQL is what is known as a 'Declarative language', which means we &lt;strong&gt;Declare&lt;/strong&gt; what we want, and the database figures out the best way to execute instructions to return the results of our query. &lt;br&gt;
A special module called the &lt;strong&gt;Planner&lt;/strong&gt; is responsible for figuring out the best 'plan' to execute the query, and the &lt;code&gt;EXPLAIN&lt;/code&gt; command allows us to see that plan.&lt;/p&gt;
&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;Using the &lt;code&gt;EXPLAIN&lt;/code&gt; command is as simple as prepending it to your normal query, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;EXPLAIN&lt;/span&gt; &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;database_name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;will return the estimated plan and cost in plain text (though you can change the output format as we will see next).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ANALYZE&lt;/code&gt; can also be prepended with &lt;code&gt;EXPLAIN&lt;/code&gt; to run the query and output the actual run statistics.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Note: This will also run your query, so be careful not to alter the database!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Interpreting the Output
&lt;/h2&gt;

&lt;p&gt;The output generated by the &lt;code&gt;EXPLAIN&lt;/code&gt; command contains details about the sequence of steps that PostgreSQL will take to retrieve the data. &lt;/p&gt;

&lt;p&gt;Some of the components we see in the output are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Node Types: Node types represent the different operations performed during the query execution.&lt;/li&gt;
&lt;li&gt;Common node types include: "Seq Scan" (sequential scan), "Index Scan" (index scan), "Nested Loop", ...etc.&lt;/li&gt;
&lt;li&gt;Join Types: If the query involves joining multiple tables, you will see the type of join used.&lt;/li&gt;
&lt;li&gt;join types include: "Nested Loop Join", "Hash Join", and "Merge Join".&lt;/li&gt;
&lt;li&gt;Relation Information: For each node, you'll find details about the involved relations or tables (their names, aliases, and access methods, ...etc).&lt;/li&gt;
&lt;li&gt;Filter Conditions: Filter conditions applied during the execution.&lt;/li&gt;
&lt;li&gt;Costs: The cost of each operation during query execution, it reflects the computational effort required, and it helps the planner choose the most efficient execution plan.&lt;/li&gt;
&lt;li&gt;Execution Order: The order in which nodes are processed.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Performance optimizations
&lt;/h2&gt;

&lt;p&gt;Here are some tips for optimizing queries once you have the output of &lt;code&gt;EXPLAIN&lt;/code&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Look for Sequential Scans: Sequential scans can be slow on large tables. These can be mitigated by creating indexes on columns frequently used in &lt;code&gt;WHERE&lt;/code&gt; clauses or &lt;code&gt;JOIN&lt;/code&gt; conditions to speed up queries.&lt;/li&gt;
&lt;li&gt;Large Sort Operations: Sorting large datasets can be resource-intensive and is best avoided. Ensure you have indexes on columns used in ORDER BY clauses.
Consider Caching: If you notice repetitive queries in the output, caching might be beneficial to reduce database load.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  References
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://www.crunchydata.com/blog/get-started-with-explain-analyze" rel="noopener noreferrer"&gt;https://www.crunchydata.com/blog/get-started-with-explain-analyze&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>postgres</category>
      <category>postgressql</category>
    </item>
    <item>
      <title>PostgreSQL Foreign Data Wrapper (FDW)</title>
      <dc:creator>Youssef</dc:creator>
      <pubDate>Thu, 20 Jul 2023 10:01:38 +0000</pubDate>
      <link>https://dev.to/yosefahab/postgresql-foreign-data-wrapper-fdw-11ig</link>
      <guid>https://dev.to/yosefahab/postgresql-foreign-data-wrapper-fdw-11ig</guid>
      <description>&lt;p&gt;Recently i've been exposed to the idea of foreign data wrappers in Postgres, and thought i'd share what i've learned so far.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is it?
&lt;/h2&gt;

&lt;p&gt;The idea behind it is simple: being able to access and interact with data stored in remote (external) databases (i.e databases that live on different machines) &lt;u&gt;as if they were regular database tables&lt;/u&gt;.&lt;br&gt;
PostgreSQL provides this feature through an extension called &lt;strong&gt;postgres_fdw&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;The general steps to setup and use the extension are as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install FDW extension, &lt;strong&gt;postgres_fdw&lt;/strong&gt; comes pre-installed with Postgres and is officially supported. But you can also use other extensions.&lt;/li&gt;
&lt;li&gt;Create server, use the &lt;code&gt;CREATE SERVER&lt;/code&gt; statement to define a connection to the remote data source.&lt;/li&gt;
&lt;li&gt;Create user mapping, create a user mapping to associate a local PostgreSQL user with a remote user for authentication purposes.&lt;/li&gt;
&lt;li&gt;Create foreign table, use the &lt;code&gt;CREATE FOREIGN TABLE&lt;/code&gt; statement to define the structure/schema of the foreign table (column names, data types, ...etc). There is also a command to automatically import the schema.&lt;/li&gt;
&lt;li&gt;Querying foreign tables, you can finally interact with foreign tables as if they were regular local tables. 
Using normal SQL (Select, insert, ...etc).
A good tip here would be to optimize performance, you can do so by pushing down operations to the remote server, i.e asking the foreign server to perform the cost estimate (&lt;code&gt;EXPLAIN&lt;/code&gt; command) by setting the &lt;strong&gt;use_remote_estimate&lt;/strong&gt; option to true on the server or table level&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;You can follow a step-by-step tutorial through a &lt;a href="https://dbsguru.com/steps-to-setup-a-foreign-data-wrapperpostgres_fdw-in-postgresql/#"&gt;helpful guide&lt;/a&gt; i found, though one thing to note if you don't have another machine to test fdw is that you can actually use the same machine and 2 seperate databases.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://www.crunchydata.com/blog/understanding-postgres_fdw"&gt;https://www.crunchydata.com/blog/understanding-postgres_fdw&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dbsguru.com/steps-to-setup-a-foreign-data-wrapperpostgres_fdw-in-postgresql/#"&gt;https://dbsguru.com/steps-to-setup-a-foreign-data-wrapperpostgres_fdw-in-postgresql/#&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>postgres</category>
      <category>postgrsql</category>
    </item>
    <item>
      <title>Getting comfortable with PostgreSQL</title>
      <dc:creator>Youssef</dc:creator>
      <pubDate>Fri, 14 Jul 2023 14:09:58 +0000</pubDate>
      <link>https://dev.to/yosefahab/getting-comfortable-with-postgresql-18d3</link>
      <guid>https://dev.to/yosefahab/getting-comfortable-with-postgresql-18d3</guid>
      <description>&lt;p&gt;In this post i will talk about some Postgres basics.&lt;br&gt;
I will assume you have already installed Postgresql.11+ and that you have basic terminal skills.&lt;/p&gt;

&lt;h2&gt;
  
  
  Utilities
&lt;/h2&gt;

&lt;p&gt;First, navigate into the postgres directory where it exists, you'll find many files and directories, but we're concerned with the &lt;code&gt;bin/&lt;/code&gt; directory, which is where you'll find postgres utilities that we'll be using.&lt;/p&gt;

&lt;h2&gt;
  
  
  Clusters
&lt;/h2&gt;

&lt;p&gt;Next, run the &lt;code&gt;initdb&lt;/code&gt; utility inside the &lt;code&gt;bin/&lt;/code&gt; directory and provide the name for your database cluster using the -D flag&lt;br&gt;
&lt;code&gt;bin/initdb -D your-cluster-name&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;A Database Cluster is a collection of databases. Each cluster is managed by a PostgreSQL server which runs on a single host.&lt;br&gt;
Clusters are stored as a directory referred to as base directory. You can refer to my &lt;a href="https://dev.to/yosefahab/postgresql-summary-pt1-4131"&gt;guide&lt;/a&gt; for more information if you're interested.&lt;/p&gt;

&lt;p&gt;This will initialize a database cluster which we will be using to create databases.&lt;/p&gt;

&lt;h2&gt;
  
  
  pg_ctl
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;pg_ctl&lt;/code&gt; utility is used to manage Postgres servers and processes.&lt;br&gt;
Run &lt;code&gt;bin/pg_ctl -D your-cluster-name&lt;/code&gt; to start the Postgres server for the cluster you just created. By default, Postgres will use port 5432&lt;/p&gt;

&lt;h2&gt;
  
  
  psql
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;psql&lt;/code&gt; utility is used to start an interactive shell with your database cluster so that you can use SQL like you would with any other DBMS.&lt;br&gt;
Run &lt;code&gt;bin/psql -l&lt;/code&gt; to list all available databases in your cluster. In Postgres version 11+ clusters are created with 3 default databases: &lt;code&gt;Postgres, Sample0, Sample1&lt;/code&gt;&lt;br&gt;
Run &lt;code&gt;bin/psql postgres&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;you can exit this shell using \q&lt;/li&gt;
&lt;li&gt;type 'help' to see the help prompt&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  SQL commands
&lt;/h2&gt;

&lt;p&gt;Let's create a new database using the command&lt;br&gt;
&lt;code&gt;CREATE DATABASE your-database-name;&lt;/code&gt; (Don't forget the semicolon!)&lt;br&gt;
now run &lt;code&gt;\l&lt;/code&gt; to view all the databases again (from inside the shell this time), you can see the new database was created.&lt;br&gt;
Now instead of exiting and reconnecting to the new database, you can instead use &lt;code&gt;\c your-database-name&lt;/code&gt; to directly switch to it.&lt;/p&gt;

&lt;p&gt;This should be enough to get you started exploring Postgres.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>PostgreSQL Summary Pt8</title>
      <dc:creator>Youssef</dc:creator>
      <pubDate>Mon, 10 Jul 2023 11:48:28 +0000</pubDate>
      <link>https://dev.to/yosefahab/postgresql-summary-pt8-cg5</link>
      <guid>https://dev.to/yosefahab/postgresql-summary-pt8-cg5</guid>
      <description>&lt;p&gt;Continuing on &lt;a href="https://dev.to/yosefahab/postgresql-summary-pt7-3pdn"&gt;part 7&lt;/a&gt;, i'll be discussing XLOG records, and the part they play in database recovery.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing of XLOG Records
&lt;/h2&gt;

&lt;p&gt;We'll explore the internal function &lt;strong&gt;exec_simple_query()&lt;/strong&gt; by invoking the following query: &lt;code&gt;INSERT INTO tbl VALUES ('A');&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The pseudo code of &lt;strong&gt;exec_simple_query()&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;exec_simple_query&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;postgres&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;ExtendCLOG&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;clog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;                  &lt;span class="cm"&gt;/* Write the state of this transaction
                                           * "IN_PROGRESS" to the CLOG.
                                           */&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;heap_insert&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;heapam&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;                &lt;span class="cm"&gt;/* Insert a tuple, creates a XLOG record,
                                           * and invoke the function XLogInsert.
                                           */&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="n"&gt;XLogInsert&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;xlog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;9.5&lt;/span&gt; &lt;span class="n"&gt;or&lt;/span&gt; &lt;span class="n"&gt;later&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;xloginsert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                                          &lt;span class="cm"&gt;/* Write the XLOG record of the inserted tuple
                                           *  to the WAL buffer, and update page's pd_lsn.
                                           */&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;finish_xact_command&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;postgres&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;     &lt;span class="cm"&gt;/* Invoke commit action.*/&lt;/span&gt;   
      &lt;span class="n"&gt;XLogInsert&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;xlog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;9.5&lt;/span&gt; &lt;span class="n"&gt;or&lt;/span&gt; &lt;span class="n"&gt;later&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;xloginsert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                                          &lt;span class="cm"&gt;/* Write a XLOG record of this commit action 
                                           * to the WAL buffer.
                                           */&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="n"&gt;XLogWrite&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;xlog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;                 &lt;span class="cm"&gt;/* Write and flush all XLOG records on 
                                           * the WAL buffer to WAL segment.
                                           */&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;TransactionIdCommitTree&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;transam&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;  &lt;span class="cm"&gt;/* Change the state of this transaction 
                                           * from "IN_PROGRESS" to "COMMITTED" on the CLOG.
                                           */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Explanation:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;ExtendCLOG()&lt;/strong&gt; writes the state of this transaction &lt;strong&gt;IN_PROGRESS&lt;/strong&gt; in the (in-memory) CLOG.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;heap_insert()&lt;/strong&gt; inserts a heap tuple into the target page on the shared buffer pool, creates this page's XLOG record, and invokes &lt;strong&gt;XLogInsert()&lt;/strong&gt;. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;XLogInsert()&lt;/strong&gt; writes the XLOG record created by the &lt;em&gt;heap_insert()&lt;/em&gt; to the WAL buffer at &lt;em&gt;LSN_1&lt;/em&gt;, and then updates the modified page's &lt;strong&gt;pd_lsn&lt;/strong&gt; &lt;em&gt;from LSN_0 to LSN_1&lt;/em&gt;. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;finish_xact_command()&lt;/strong&gt;, which is invoked to commit this transaction, creates this commit action's XLOG record, and then &lt;strong&gt;XLogInsert()&lt;/strong&gt; writes this record into the WAL buffer at &lt;strong&gt;LSN_2&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;XLogWrite()&lt;/strong&gt; writes and flushes all XLOG records on the WAL buffer to the WAL segment file.
If the parameter &lt;em&gt;wal_sync_method&lt;/em&gt; is set to &lt;em&gt;'open_sync'&lt;/em&gt; or &lt;em&gt;'open_datasync'&lt;/em&gt;, the records are synchronously written because the function writes all records with the &lt;em&gt;open()&lt;/em&gt; system call specified the flag &lt;em&gt;O_SYNC&lt;/em&gt; or &lt;em&gt;O_DSYNC&lt;/em&gt;. If the parameter is set to &lt;em&gt;'fsync'&lt;/em&gt;, &lt;em&gt;'fsync_writethrough'&lt;/em&gt; or &lt;em&gt;'fdatasync'&lt;/em&gt;, the respective system call – &lt;em&gt;fsync()&lt;/em&gt;, &lt;em&gt;fcntl() with F_FULLFSYNC option&lt;/em&gt;, or &lt;em&gt;fdatasync()&lt;/em&gt; – will be executed. &lt;em&gt;In any case, all XLOG records are ensured to be written into the storage&lt;/em&gt;. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TransactionIdCommitTree()&lt;/strong&gt; changes the state of this transaction &lt;em&gt;from IN_PROGRESS to COMMITTED&lt;/em&gt; on the CLOG.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  WAL Writer Process
&lt;/h2&gt;

&lt;p&gt;It is a background process to check the WAL buffer periodically and write all unwritten XLOG records into the WAL segments.&lt;/p&gt;

&lt;p&gt;The purpose of this process is to improves performance by avoiding bursts of of XLOG records writes when a large amount of data are committed at once. &lt;/p&gt;

&lt;p&gt;This process cannot be disabled, and it checks the WAL buffer every 200 ms by default, this interval can by changed using the configuration parameter &lt;strong&gt;wal_writer_delay&lt;/strong&gt;.'&lt;/p&gt;

&lt;h2&gt;
  
  
  Checkpoint Processing in PostgreSQL
&lt;/h2&gt;

&lt;p&gt;Checkpointing in PostgreSQL is performed by the checkpointer background process, it has two responsibilities: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Preparation of database recovery.&lt;/li&gt;
&lt;li&gt;Cleaning of dirty pages on the shared buffer pool.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It starts when one of the following occurs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A superuser issues &lt;code&gt;CHECKPOINT&lt;/code&gt; command manually.&lt;/li&gt;
&lt;li&gt;The interval time set for &lt;strong&gt;checkpoint_timeout&lt;/strong&gt; from the previous checkpoint has exceeded 300secs.&lt;/li&gt;
&lt;li&gt;(version 9.4 or earlier) The number of WAL segment files (3 by default) set for &lt;strong&gt;checkpoint_segments&lt;/strong&gt; has been consumed since the previous checkpoint.&lt;/li&gt;
&lt;li&gt;(version 9.5 or later) The total size of the WAL segment files in the &lt;strong&gt;pg_xlog&lt;/strong&gt; (called pg_wal in version 10 or later) has exceeded the value of the parameter &lt;strong&gt;max_wal_size&lt;/strong&gt; (1GB (64 files) by default).&lt;/li&gt;
&lt;li&gt;PostgreSQL server stops in smart or fast mode.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  pg_control File
&lt;/h3&gt;

&lt;p&gt;This file contains fundamental information required by the checkpointer process, which is essential for database recovery.&lt;/p&gt;

&lt;p&gt;This file stores over 40 items, however i'll be talking about three specific items:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;State&lt;/strong&gt;: The state of database server at the time of the latest checkpointing starts. &lt;br&gt;
There are seven states in total, some of which are:&lt;br&gt;
   1. &lt;strong&gt;start up&lt;/strong&gt; is the state that system is starting up.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;shut down&lt;/strong&gt; is the state that system is going down normally by the shutdown command&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;in production&lt;/strong&gt; is the state that system is running.&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Latest checkpoint location&lt;/strong&gt;: LSN Location of the latest checkpoint record. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Prior checkpoint location&lt;/strong&gt; (deprecated in version 11): LSN Location of the prior checkpoint record .&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A pg_control file is stored in the global subdirectory under the base-directory; its contents can be shown using the &lt;strong&gt;pg_controldata&lt;/strong&gt; utility.&lt;/p&gt;

&lt;h3&gt;
  
  
  To summarize
&lt;/h3&gt;

&lt;p&gt;The checkpointer creates the &lt;strong&gt;checkpoint record&lt;/strong&gt; which contains the &lt;strong&gt;REDO point&lt;/strong&gt;, stores the checkpoint location into the &lt;strong&gt;pg_control&lt;/strong&gt; file.&lt;br&gt;
This allows PostgreSQL to recover itself &lt;em&gt;by replaying WAL data from the REDO point&lt;/em&gt; which is obtained from the checkpoint record provided by the &lt;strong&gt;pg_control&lt;/strong&gt; file.&lt;/p&gt;

&lt;h4&gt;
  
  
  References
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://www.interdb.jp/pg/pgsql09.html"&gt;https://www.interdb.jp/pg/pgsql09.html&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>postgres</category>
      <category>postgressql</category>
    </item>
    <item>
      <title>PostgreSQL Summary Pt7</title>
      <dc:creator>Youssef</dc:creator>
      <pubDate>Sat, 08 Jul 2023 22:29:20 +0000</pubDate>
      <link>https://dev.to/yosefahab/postgresql-summary-pt7-3pdn</link>
      <guid>https://dev.to/yosefahab/postgresql-summary-pt7-3pdn</guid>
      <description>&lt;p&gt;Write Ahead Log (WAL) is a transaction logging mechanism implemented in PostgreSQL 7.1. &lt;br&gt;
I'll be discussing some things needed to understand WAL.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why is it useful?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;It ensures that no data is lost even when a system failure occurs.&lt;/li&gt;
&lt;li&gt;It also makes possible the implementation of Point-in-Time Recovery (PITR) and Streaming Replication (SR). &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How?
&lt;/h3&gt;

&lt;p&gt;The log contains information about each transaction executed, allowing database server to recover the database cluster by &lt;strong&gt;replaying&lt;/strong&gt; changes and actions.&lt;/p&gt;

&lt;p&gt;Here are some points that will be useful later:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Postgres writes all modifications as history data (aka &lt;strong&gt;XLOG records&lt;/strong&gt; or &lt;strong&gt;WAL data&lt;/strong&gt;) to persistent storage.&lt;/li&gt;
&lt;li&gt;XLOG records are written into a buffer in memory called &lt;strong&gt;WAL buffer&lt;/strong&gt;. When a transaction commits or aborts (and others), they are immediately written into a &lt;strong&gt;WAL segment file&lt;/strong&gt; on the storage. &lt;/li&gt;
&lt;li&gt;As mentioned in &lt;a href="https://dev.to/yosefahab/postgresql-summary-pt2-5cnh"&gt;part 2&lt;/a&gt;, &lt;strong&gt;LSN (Log Sequence Number)&lt;/strong&gt; is the unique id of an XLOG record and represents the location where it is written on the transaction log.&lt;/li&gt;
&lt;li&gt;Postgres starts to recover from the &lt;strong&gt;REDO point&lt;/strong&gt;, which is the location to write the XLOG record at the moment when the latest &lt;strong&gt;checkpoint&lt;/strong&gt; is started.&lt;/li&gt;
&lt;li&gt;The database &lt;em&gt;recovery process&lt;/em&gt; and the &lt;em&gt;checkpoint process&lt;/em&gt; always occur together.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Insertion with WAL
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QhCScq_O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zyq2hzbif89t3rlsfvgb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QhCScq_O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zyq2hzbif89t3rlsfvgb.png" alt="Insertion with WAL" width="800" height="396"&gt;&lt;/a&gt;&lt;br&gt;
The following are the steps that Postgres performs when an &lt;code&gt;INSERT&lt;/code&gt; statement is issued:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Whenever the checkpointer starts, it writes an XLOG record called &lt;strong&gt;checkpoint record&lt;/strong&gt; to the current WAL segment. This record contains the location of the latest &lt;em&gt;REDO point&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Issuing the first INSERT statement, PostgreSQL loads the database table's page into the shared buffer pool, inserts a tuple into the page, creates and writes a XLOG record of this statement into the WAL buffer at the location &lt;em&gt;LSN_1&lt;/em&gt;, and updates the table's LSN from &lt;em&gt;LSN_0&lt;/em&gt; to &lt;em&gt;LSN_1&lt;/em&gt;. 
&lt;/li&gt;
&lt;li&gt;As this transaction commits, PostgreSQL creates and writes a XLOG record of this commit action into the WAL buffer, and then, writes and flushes all XLOG records on the WAL buffer to the WAL segment file, from &lt;em&gt;LSN_1&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Issuing the second INSERT statement, PostgreSQL inserts a new tuple into the page, creates and writes this tuple's XLOG record to the WAL buffer at &lt;em&gt;LSN_2&lt;/em&gt;, and updates the table's LSN from &lt;em&gt;LSN_1&lt;/em&gt; to &lt;em&gt;LSN_2&lt;/em&gt;. &lt;/li&gt;
&lt;li&gt;When this statement's transaction commits, PostgreSQL operates in the same manner as in step (3).&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  WAL Segment structure
&lt;/h2&gt;

&lt;p&gt;A WAL segment is a 16 MB file, by default, and it is internally divided into pages of 8192 bytes (8 KB). &lt;/p&gt;

&lt;p&gt;The first page has a header-data defined by the structure &lt;a href="https://github.com/postgres/postgres/blob/master/src/include/access/xlog_internal.h"&gt;XLogLongPageHeaderData&lt;/a&gt;, while the headings of all other pages have the page information defined by the structure XLogPageHeaderData. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Following the page header&lt;/em&gt;, XLOG records are written in each page from the beginning in descending order. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CtNKApiM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4qzd3etsr2hvt7bfjxw2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CtNKApiM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4qzd3etsr2hvt7bfjxw2.png" alt="WAL Segment Structure" width="800" height="343"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  XLOG Record Structure
&lt;/h2&gt;

&lt;p&gt;An XLOG record comprises the general header portion and each associated data portion.&lt;/p&gt;

&lt;h3&gt;
  
  
  Header Structure
&lt;/h3&gt;

&lt;p&gt;The header structure is the same for all XLOG records. It consists of the following fields:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;version&lt;/code&gt;: The XLOG record version number.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;type&lt;/code&gt;: The type of XLOG record.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;timestamp&lt;/code&gt;: The timestamp of the XLOG record.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;length&lt;/code&gt;: The length of the XLOG record.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Data Portion (Version 9.4 or Earlier)
&lt;/h3&gt;

&lt;p&gt;The data portion of an XLOG record in version 9.4 or earlier is specific to the type of XLOG record. For example, the data portion of a &lt;code&gt;COMMIT&lt;/code&gt; XLOG record contains the transaction ID of the committed transaction.&lt;/p&gt;

&lt;h3&gt;
  
  
  Data Portion (Version 9.5)
&lt;/h3&gt;

&lt;p&gt;The data portion of an XLOG record in version 9.5 has a common format. It consists of the following fields:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;data_header&lt;/code&gt;: A header that describes the data portion.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;data&lt;/code&gt;: The actual data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;data_header&lt;/code&gt; field contains the following information:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;data_format&lt;/code&gt;: The data format version number.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;data_length&lt;/code&gt;: The length of the &lt;code&gt;data&lt;/code&gt; field.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;data&lt;/code&gt; field can contain any type of data. The specific format of the data is determined by the &lt;code&gt;data_format&lt;/code&gt; field.&lt;/p&gt;

&lt;h4&gt;
  
  
  References
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://www.interdb.jp/pg/pgsql09.html"&gt;https://www.interdb.jp/pg/pgsql09.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.postgresql.org/docs/current/wal-intro.html"&gt;https://www.postgresql.org/docs/current/wal-intro.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Write-ahead_logging"&gt;https://en.wikipedia.org/wiki/Write-ahead_logging&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.interdb.jp/blog/pgsql/pg95walformat/"&gt;https://www.interdb.jp/blog/pgsql/pg95walformat/&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>postgres</category>
      <category>postgressql</category>
    </item>
    <item>
      <title>PostgreSQL Summary Pt6</title>
      <dc:creator>Youssef</dc:creator>
      <pubDate>Thu, 29 Jun 2023 11:11:07 +0000</pubDate>
      <link>https://dev.to/yosefahab/postgresql-summary-pt6-41fk</link>
      <guid>https://dev.to/yosefahab/postgresql-summary-pt6-41fk</guid>
      <description>&lt;p&gt;In this part i'll be discussing the VACUUM process in Postgres.&lt;/p&gt;

&lt;p&gt;VACUUM is a maintenance process that facilitates the persistent operation of PostgreSQL. Its two main tasks are &lt;strong&gt;removing dead tuples&lt;/strong&gt; and &lt;strong&gt;freezing transaction ids&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To remove dead tuples, vacuum processing provides two modes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Concurrent VACUUM&lt;/strong&gt;: Often  called VACUUM, removes dead tuples for each page of the table file. &lt;em&gt;Other transactions can read the table while this process is running&lt;/em&gt;. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Full VACUUM&lt;/strong&gt;: Removes dead tuples and defragments live tuples. &lt;em&gt;Other transactions *cannot access tables while Full VACUUM is running&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Outline of Concurrent VACUUM
&lt;/h2&gt;

&lt;p&gt;Vacuum processing performs the following tasks for specified tables or all tables in the database.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Removing dead tuples

&lt;ul&gt;
&lt;li&gt;Remove dead tuples and defragment live tuples for each page.&lt;/li&gt;
&lt;li&gt;Remove index tuples that point to dead tuples.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Freezing old txids

&lt;ul&gt;
&lt;li&gt;Freeze old txids of tuples if necessary.&lt;/li&gt;
&lt;li&gt;Update frozen txid related system catalogs (pg_database and pg_class).&lt;/li&gt;
&lt;li&gt;Remove unnecessary parts of the clog if possible.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Others

&lt;ul&gt;
&lt;li&gt;Update the FSM and VM of processed tables.&lt;/li&gt;
&lt;li&gt;Update several statistics (pg_stat_all_tables, etc).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Following is pseudocode of concurrent VACUUM, and it can be described in &lt;em&gt;three blocks&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FOR each table
    Acquire ShareUpdateExclusiveLock lock for the target table
    /* The first block */
    Scan all pages to get all dead tuples, and freeze old tuples if necessary 
    Remove the index tuples that point to the respective dead tuples if exists

    /* The second block */
    FOR each page of the table
        Remove the dead tuples, and Reallocate the live tuples in the page
        Update FSM and VM
    END FOR

  /* The third block */
   Clean up indexes
   Truncate the last page if possible
   Update both the statistics and system catalogs of the target table
   Release ShareUpdateExclusiveLock lock
END FOR

/* Post-processing */
Update statistics and system catalogs
Remove both unnecessary files and pages of the clog if possible
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  First Block
&lt;/h3&gt;

&lt;p&gt;This block performs freeze processing and &lt;em&gt;removes index tuples that point to dead tuples&lt;/em&gt;.&lt;br&gt;
First, PostgreSQL scans a target table to build a list of dead tuples and freeze old tuples if possible. The list is stored in &lt;strong&gt;maintenance_work_mem&lt;/strong&gt; in local memory.&lt;br&gt;
Then it performs a &lt;em&gt;cleanup stage&lt;/em&gt;, where it removes index tuples by referring to the dead tuple list. &lt;br&gt;
&lt;em&gt;This process is costly&lt;/em&gt;. In version 10 or earlier, the cleanup stage is always executed. In version 11 or later, if the target index is B-tree, whether the cleanup stage is executed or not  is decided by the configuration parameter &lt;strong&gt;vacuum_cleanup_index_scale_factor&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Second Block
&lt;/h3&gt;

&lt;p&gt;This block removes dead tuples and updates both the FSM and VM for each page of the table.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Note: &lt;em&gt;unnecessary line pointers are not removed and they will be reused in future&lt;/em&gt;. This is because, if line pointers are removed, all index tuples of the associated indexes must be updated.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Third Block
&lt;/h3&gt;

&lt;p&gt;The third block performs the cleanup after the deletion of the indexes, and also updates both the statistics and system catalogs related to vacuum processing for each target table. Moreover, if the last page has no tuples, it is truncated from the table file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Post-processing
&lt;/h3&gt;

&lt;p&gt;When vacuum processing is complete, PostgreSQL updates both several statistics and system catalogs related to vacuum processing, and it removes unnecessary parts of the clog if possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Visibility Map
&lt;/h2&gt;

&lt;p&gt;Since vacuum processing involves scanning whole tables, it is a costly process. VM was introduced in version 8.4 to reduce this cost.&lt;/p&gt;

&lt;p&gt;Each table has an individual visibility map that holds the visibility of each page in the table file, allowing Postgres to quickly identify dead tuples. This allows VACUUM to process only the dead tuples and skip the rest. &lt;/p&gt;

&lt;h2&gt;
  
  
  Freeze Processing
&lt;/h2&gt;

&lt;p&gt;Freeze processing has two modes:&lt;/p&gt;

&lt;h3&gt;
  
  
  Lazy Mode
&lt;/h3&gt;

&lt;p&gt;freeze processing scans only pages that contain dead tuples using the respective VM of the target tables.&lt;/p&gt;

&lt;p&gt;When starting freeze processing, PostgreSQL calculates the freezeLimit txid and &lt;em&gt;freezes tuples whose t_xmin is less than the freezeLimit txid&lt;/em&gt;.&lt;br&gt;
The freezeLimit txid is defined as: &lt;br&gt;
&lt;code&gt;freezeLimit_txid = (OldestXmin − vacuum_freeze_min_age)&lt;/code&gt;&lt;br&gt;
where &lt;strong&gt;OldestXmin&lt;/strong&gt; is the oldest txid among currently running transactions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Eager Mode
&lt;/h3&gt;

&lt;p&gt;scans all pages regardless of whether each page contains dead tuples or not, and it also updates system catalogs related to freeze processing and removes unnecessary parts of the clog if possible.&lt;/p&gt;

&lt;p&gt;Eager mode is performed when the following condition is satisfied.&lt;br&gt;
&lt;code&gt;pg_database.datfrozenxid &amp;lt; (OldestXmin − vacuum_freeze_table_age)&lt;/code&gt;&lt;br&gt;
where &lt;strong&gt;pg_database.datfrozenxid&lt;/strong&gt; represents the columns of the &lt;strong&gt;pg_database&lt;/strong&gt; system catalog and holds the oldest frozen txid for each database.&lt;/p&gt;

&lt;h2&gt;
  
  
  Autovacuum Daemon
&lt;/h2&gt;

&lt;p&gt;Vacuum processing has been automated with the autovacuum daemon; thus, the operation of PostgreSQL has become extremely easy.&lt;/p&gt;

&lt;h4&gt;
  
  
  References
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://www.interdb.jp/pg/pgsql06.html"&gt;https://www.interdb.jp/pg/pgsql06.html&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>postgres</category>
      <category>postgressql</category>
    </item>
    <item>
      <title>PostgreSQL Summary Pt5</title>
      <dc:creator>Youssef</dc:creator>
      <pubDate>Wed, 28 Jun 2023 13:55:50 +0000</pubDate>
      <link>https://dev.to/yosefahab/postgresql-summary-pt5-1340</link>
      <guid>https://dev.to/yosefahab/postgresql-summary-pt5-1340</guid>
      <description>&lt;p&gt;In this part i will discuss basic information required for understanding concurrency control in Postgres.&lt;/p&gt;

&lt;p&gt;PostgreSQL uses a variation of Multi-version Concurrency Control (MVCC) called &lt;strong&gt;Snapshot Isolation (SI)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In MVCC, Each write operation creates a new version of a data item while retaining the old version. When a transaction reads a data item, the system selects one of the versions to ensure isolation of the individual transaction. The main advantage of MVCC is that &lt;em&gt;readers don’t block writers, and writers don’t block readers&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In SI, A new data item is inserted directly into the relevant table page. When reading items, PostgreSQL selects the appropriate version of an item in response to an individual transaction by applying &lt;strong&gt;visibility check rules&lt;/strong&gt; (will talk about this later).&lt;/p&gt;

&lt;h2&gt;
  
  
  Transaction ID
&lt;/h2&gt;

&lt;p&gt;Whenever a transaction begins, a unique identifier, referred to as a &lt;strong&gt;transaction id (txid)&lt;/strong&gt;, which is a 32-bit unsigned integer assigned by the &lt;strong&gt;transaction manager&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The built-in &lt;em&gt;txid_current()&lt;/em&gt; function can be used after a transaction starts to check the current txid.&lt;/p&gt;

&lt;p&gt;However there are three special txids reserved by Postgres:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;0&lt;/strong&gt;:&lt;strong&gt;Invalid&lt;/strong&gt; txid.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;1&lt;/strong&gt;:&lt;strong&gt;Bootstrap&lt;/strong&gt; txid, which is only used in the initialization of the database cluster.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2&lt;/strong&gt;:&lt;strong&gt;Frozen&lt;/strong&gt; txid.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Txids are sequential, and for a given id n, all &lt;em&gt;ids &amp;gt; n are invisible to it&lt;/em&gt;, and all &lt;em&gt;ids &amp;lt; n are visible&lt;/em&gt; to it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tuple Structure
&lt;/h2&gt;

&lt;p&gt;A heap tuple consists of three parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;HeapTupleHeaderData structure&lt;/li&gt;
&lt;li&gt;NULL bitmap&lt;/li&gt;
&lt;li&gt;user data&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here are four relevant fields of the HeapTupleHeaderData:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;t_xmin&lt;/strong&gt; holds the txid of the transaction that inserted this tuple.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;t_xmax&lt;/strong&gt; holds the txid of the transaction that deleted or updated this tuple. If this tuple has not been deleted or updated, t_xmax is set to &lt;em&gt;0&lt;/em&gt;, which means INVALID.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;t_cid&lt;/strong&gt; holds the command id (cid), which means how many SQL commands were executed before this command was executed within the current transaction beginning from 0.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;t_ctid&lt;/strong&gt; holds the tuple identifier (tid) that points to itself or a new tuple. tid is used to identify a tuple within a table. When this tuple is updated, the t_ctid of this tuple points to the new tuple; otherwise, the t_ctid points to itself.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Free Space Map (FSM)
&lt;/h2&gt;

&lt;p&gt;When inserting a heap or an index tuple, PostgreSQL uses the &lt;strong&gt;FSM&lt;/strong&gt; of the corresponding table or index to select the page which can be inserted it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Commit Log (clog)
&lt;/h2&gt;

&lt;p&gt;PostgreSQL holds the statuses of transactions in the &lt;strong&gt;Commit Log&lt;/strong&gt; (often called the &lt;strong&gt;clog&lt;/strong&gt;). It is allocated to the shared memory, and is used throughout transaction processing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Transaction Status
&lt;/h3&gt;

&lt;p&gt;PostgreSQL defines four transaction states:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;IN_PROGRESS&lt;/li&gt;
&lt;li&gt;COMMITTED&lt;/li&gt;
&lt;li&gt;ABORTED&lt;/li&gt;
&lt;li&gt;SUB_COMMITTED (for sub-transactions)&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;p&gt;The clog comprises one or more 8 KB pages in shared memory. The clog logically forms an array. The indices of the array correspond to the respective transaction ids, and each item in the array holds the status of the corresponding transaction id.&lt;/p&gt;

&lt;h3&gt;
  
  
  Maintenance of the Clog
&lt;/h3&gt;

&lt;p&gt;When PostgreSQL shuts down or whenever the checkpoint process runs, the data of the clog are written into files stored under the &lt;strong&gt;pg_xact&lt;/strong&gt; subdirectory (called &lt;em&gt;pg_clog&lt;/em&gt; in Version 9.6 or earlier.) These files are named &lt;em&gt;0000&lt;/em&gt;, &lt;em&gt;0001&lt;/em&gt;.&lt;br&gt;
When PostgreSQL starts up, the data stored in the pg_xact's files are loaded to initialize the clog.&lt;br&gt;
The size of the clog continuously increases on each new page, but since not all data in the clog are necessary, the VACUUM process regularly removes old data (both the clog pages and files).&lt;/p&gt;

&lt;h2&gt;
  
  
  Transaction Snapshot
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;transaction snapshot&lt;/strong&gt; is a dataset that stores information about whether all transactions are active at a certain point in time for an individual transaction. Here an active transaction means it is in progress or has not yet started. &lt;/p&gt;

&lt;p&gt;When using the obtained snapshot for the visibility check, &lt;em&gt;active&lt;/em&gt; transactions in the snapshot must be treated as &lt;em&gt;in progress&lt;/em&gt; even if they have actually been committed or aborted. This rule is important because it causes the difference in the behaviour between READ COMMITTED and REPEATABLE READ.&lt;/p&gt;

&lt;h2&gt;
  
  
  Visibility Check Rules
&lt;/h2&gt;

&lt;p&gt;Visibility check rules are a set of rules used to determine whether each tuple is visible or invisible using both the &lt;strong&gt;t_xmin&lt;/strong&gt; and &lt;strong&gt;t_xmax&lt;/strong&gt; of the tuple, the clog, and the obtained transaction snapshot.&lt;/p&gt;

&lt;p&gt;Following are some minimal rules:&lt;/p&gt;

&lt;h3&gt;
  
  
  Status of t_xmin is ABORTED
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Rule 1:&lt;/strong&gt; A tuple whose t_xmin status is ABORTED is always &lt;em&gt;invisible&lt;/em&gt;  because the transaction that inserted this tuple has been aborted.&lt;/p&gt;

&lt;h3&gt;
  
  
  Status of t_xmin is IN_PROGRESS
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Rules 3 &amp;amp; 4&lt;/strong&gt;: A tuple whose t_xmin status is IN_PROGRESS is &lt;em&gt;invisible&lt;/em&gt;, except under one condition.&lt;/p&gt;

&lt;h3&gt;
  
  
  Status of t_xmin is COMMITTED
&lt;/h3&gt;

&lt;p&gt;A tuple whose t_xmin status is COMMITTED is  &lt;em&gt;visible&lt;/em&gt; (Rules 6,8, and 9), except under three conditions.&lt;/p&gt;

&lt;h4&gt;
  
  
  References
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://www.interdb.jp/pg/pgsql05.html"&gt;https://www.interdb.jp/pg/pgsql05.html&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>postgres</category>
      <category>postgressql</category>
    </item>
    <item>
      <title>PostgreSQL Summary Pt3</title>
      <dc:creator>Youssef</dc:creator>
      <pubDate>Sun, 25 Jun 2023 20:57:31 +0000</pubDate>
      <link>https://dev.to/yosefahab/postgresql-summary-pt3-4841</link>
      <guid>https://dev.to/yosefahab/postgresql-summary-pt3-4841</guid>
      <description>&lt;p&gt;In this post we'll talk about Processes in Postgres as well as Memory Management.&lt;/p&gt;

&lt;h2&gt;
  
  
  Process Management
&lt;/h2&gt;

&lt;p&gt;Postgres uses a collection of processes usually referred to as a &lt;strong&gt;PostgreSQL server&lt;/strong&gt; to manage a database database cluster. &lt;/p&gt;

&lt;p&gt;It contains the following types of processes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;postgres server process&lt;/strong&gt; is a parent of all processes related to a database cluster management.&lt;/li&gt;
&lt;li&gt;Each &lt;strong&gt;backend process&lt;/strong&gt; handles all queries and statements issued by a connected client.&lt;/li&gt;
&lt;li&gt;Various &lt;strong&gt;background processes&lt;/strong&gt; perform processes of each feature (e.g., VACUUM and CHECKPOINT processes) for database management. &lt;/li&gt;
&lt;li&gt;In the &lt;strong&gt;replication associated processes&lt;/strong&gt;, they perform the streaming replication.&lt;/li&gt;
&lt;li&gt;In the &lt;strong&gt;background worker process&lt;/strong&gt; supported from version 9.3, it can perform any processing implemented by users. 
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wguMNDZS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hkf3pkgmqydm0lirfukk.png" alt="postgres processes" width="800" height="336"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Postgres Server Process
&lt;/h3&gt;

&lt;p&gt;The parent of all in a PostgreSQL server. In the earlier versions, it was called &lt;em&gt;postmaster&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;By executing the &lt;strong&gt;pg_ctl&lt;/strong&gt; utility with &lt;em&gt;start&lt;/em&gt; option, a postgres server process starts up. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Allocates a shared memory area in memory.&lt;/li&gt;
&lt;li&gt;Starts various background processes.&lt;/li&gt;
&lt;li&gt;Starts replicating associated processes and background worker processes if necessary.&lt;/li&gt;
&lt;li&gt;Waits for connection requests from clients. On receiving a connection request from a client, it starts a backend process (which handles all queries issued by the connected client.) &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A postgres server process listens to one network port, the default port is &lt;strong&gt;5432&lt;/strong&gt;. Although more than one PostgreSQL server can be run on the same host.&lt;/p&gt;

&lt;h3&gt;
  
  
  Backend Processes
&lt;/h3&gt;

&lt;p&gt;A backend process, (also called &lt;em&gt;postgres&lt;/em&gt;), is started by the postgres server process and handles all queries issued by one connected client. It communicates with the client by a single TCP connection, and terminates when the client gets disconnected.&lt;/p&gt;

&lt;p&gt;As it is allowed to operate only one database, you have to specify a database you want to use explicitly when connecting to a PostgreSQL server.&lt;/p&gt;

&lt;p&gt;PostgreSQL allows multiple clients to connect simultaneously; the configuration parameter &lt;em&gt;max_connections&lt;/em&gt; controls the maximum number of the clients (default is 100). &lt;/p&gt;

&lt;p&gt;If many clients such as Web applications frequently repeat the connection and disconnection with a PostgreSQL server, it increases both costs of establishing connections and of creating backend processes because PostgreSQL has not implemented a native connection pooling feature. Such circumstance has a negative effect on the performance of database server. To deal with such a case, a pooling middleware (either &lt;a href="https://pgbouncer.github.io/"&gt;pgbouncer&lt;/a&gt; or &lt;a href="http://www.pgpool.net/mediawiki/index.php/Main_Page"&gt;pgpool-II&lt;/a&gt;) is usually used.&lt;/p&gt;

&lt;h3&gt;
  
  
  Background Processes
&lt;/h3&gt;

&lt;p&gt;Here are the detailed description of some processes.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;process&lt;/th&gt;
&lt;th&gt;description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;background writer&lt;/td&gt;
&lt;td&gt;Writes dirty pages on the shared buffer pool gradually and regularly to a persistent storage. (In version 9.1 or earlier, it was also responsible for checkpoint process.)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;checkpointer&lt;/td&gt;
&lt;td&gt;(version 9.2+) Performs checkpointing.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;autovacuum launcher&lt;/td&gt;
&lt;td&gt;The autovacuum-worker processes are invoked for vacuum process periodically.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WAL writer&lt;/td&gt;
&lt;td&gt;Writes and flushes periodically the WAL data on the WAL buffer to persistent storage.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;statistics collector&lt;/td&gt;
&lt;td&gt;Collects statistics information such as for pg_stat_activity and for pg_stat_database, etc.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;logger&lt;/td&gt;
&lt;td&gt;Writes error messages into log files.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;archiver&lt;/td&gt;
&lt;td&gt;Archiving logging.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Memory Management
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5WWrlSMX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vxr8jb814v06vi44vw1y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5WWrlSMX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vxr8jb814v06vi44vw1y.png" alt="Memory Architecture" width="800" height="634"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Memory architecture in PostgreSQL can be classified into two broad categories:&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Local memory area
&lt;/h2&gt;

&lt;p&gt;Each backend process allocates a local memory area for query processing; each area is divided into several sub-areas – whose sizes are either fixed or variable.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;sub-area&lt;/th&gt;
&lt;th&gt;description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;work_mem&lt;/td&gt;
&lt;td&gt;Executor uses this area for &lt;em&gt;sorting tuples&lt;/em&gt; by ORDER BY and DISTINCT operations, and for &lt;em&gt;joining tables&lt;/em&gt; by merge-join and &lt;em&gt;hash-join operations&lt;/em&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;maintenance_work_mem&lt;/td&gt;
&lt;td&gt;Some kinds of &lt;em&gt;maintenance operations&lt;/em&gt; (e.g., VACUUM, REINDEX) use this area.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;temp_buffers&lt;/td&gt;
&lt;td&gt;Executor uses this area for &lt;em&gt;storing temporary tables&lt;/em&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  2. Shared memory area
&lt;/h3&gt;

&lt;p&gt;A shared memory area is allocated by a PostgreSQL server when it starts up, and is used by all processes of a PostgreSQL server. This area is also divided into several fix sized sub-areas.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;sub-area&lt;/th&gt;
&lt;th&gt;description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;shared buffer pool&lt;/td&gt;
&lt;td&gt;PostgreSQL loads pages within tables and indexes from a persistent storage to here, and operates them directly.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WAL buffer&lt;/td&gt;
&lt;td&gt;
&lt;em&gt;Buffering area of the WAL data&lt;/em&gt; before writing to a persistent storage. To ensure that no data has been lost by server failures.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;commit log&lt;/td&gt;
&lt;td&gt;
&lt;em&gt;Commit Log (CLOG)&lt;/em&gt; keeps the states of all transactions (e.g., in_progress, committed, aborted) for &lt;em&gt;Concurrency Control (CC) mechanism&lt;/em&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In addition to them, PostgreSQL allocates several other areas such as: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sub-areas for the various &lt;em&gt;access control mechanisms&lt;/em&gt;. (e.g., semaphores, lightweight locks, shared and exclusive locks, etc) &lt;/li&gt;
&lt;li&gt;Sub-areas for the various &lt;em&gt;background processes&lt;/em&gt;, such as checkpointer and autovacuum. &lt;/li&gt;
&lt;li&gt;Sub-areas for &lt;em&gt;transaction processing&lt;/em&gt; such as save-point and two-phase-commit.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>postgres</category>
      <category>postgressql</category>
    </item>
  </channel>
</rss>
