<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  
  <title>🪴 Willian Pinheiro</title>
  <subtitle>Blog</subtitle>
  <link href="https://willpinha.github.io/feed.xml" rel="self" />
  <link href="https://willpinha.github.io/" />
  <updated>2026-09-12T00:00:00Z</updated>
  <id>https://willpinha.github.io/</id>
  <author>
    <name>🪴 Willian Pinheiro</name>
  </author>
  <entry>
    <title>A Docker image is composed of .tar files</title>
    <link href="https://willpinha.github.io/blog/a-docker-image-is-composed-of-tar-files/" />
    <updated>2026-09-12T00:00:00Z</updated>
    <id>https://willpinha.github.io/blog/a-docker-image-is-composed-of-tar-files/</id>
    <content type="html">&lt;p&gt;A Docker image is a &lt;code&gt;.tar&lt;/code&gt; file that contains metadata and its respective layers. Each layer is also a &lt;code&gt;.tar&lt;/code&gt; file containing the file system diff&lt;/p&gt;
&lt;h2&gt;Example&lt;/h2&gt;
&lt;p&gt;We pull the &lt;code&gt;python&lt;/code&gt; image, save it to a &lt;code&gt;.tar&lt;/code&gt; file, and extract that file&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; pull python
&lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; save python &lt;span class=&quot;token parameter variable&quot;&gt;-o&lt;/span&gt; python.tar
&lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; python-extracted &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;tar&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-xf&lt;/span&gt; python.tar &lt;span class=&quot;token parameter variable&quot;&gt;-C&lt;/span&gt; python-extracted
&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; python-extracted&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The end result is a set of blobs. Some of these blobs are configuration files, while others are layers. The &lt;code&gt;manifest.json&lt;/code&gt; file tells us which blobs are layers&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.
├── blobs
│   └── sha256
│       ├── 375591c23c...
│       ├── 56a9d4a189...
│       ├── 92385f4b6d...
│       └── bb56896431...
│       └── ...
├── index.json
├── manifest.json
├── oci-layout
└── repositories
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To extract all layer blobs and view the file system diffs, run the script below (inside &lt;code&gt;python-extracted&lt;/code&gt;)&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;&lt;span class=&quot;token environment constant&quot;&gt;IFS&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-r&lt;/span&gt; f&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;file&lt;/span&gt; --mime-type &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$f&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-q&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;application/x-tar&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;token assign-left variable&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;dirname&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$f&lt;/span&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token assign-left variable&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;basename&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$f&lt;/span&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token assign-left variable&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${base&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;.tar}&lt;/span&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;token assign-left variable&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$dir&lt;/span&gt;/.tmp_extract_&lt;span class=&quot;token variable&quot;&gt;$base&lt;/span&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;mv&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$f&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$tmp&lt;/span&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$dir&lt;/span&gt;/&lt;span class=&quot;token variable&quot;&gt;$name&lt;/span&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;tar&lt;/span&gt; xf &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$tmp&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$dir&lt;/span&gt;/&lt;span class=&quot;token variable&quot;&gt;$name&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$tmp&lt;/span&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;done&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt; ./blobs/sha256 &lt;span class=&quot;token parameter variable&quot;&gt;-maxdepth&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-type&lt;/span&gt; f&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
</content>
  </entry>
  <entry>
    <title>How to implement a DBMS?</title>
    <link href="https://willpinha.github.io/blog/how-to-implement-a-dbms/" />
    <updated>2023-08-30T00:00:00Z</updated>
    <id>https://willpinha.github.io/blog/how-to-implement-a-dbms/</id>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This article was originally published on my Medium while I was taking database classes at the University of São Paulo&lt;/p&gt;
&lt;p&gt;A large part of this article was written on my phone during my train rides back home. Good times :-)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;DBMSs (Database Management Systems) are software created to facilitate the storage and retrieval of data in a computer system&lt;/p&gt;
&lt;p&gt;Usually, when we develop an application that accesses a DBMS, we don&#39;t think much about what happens under the hood when we interact with the stored data&lt;/p&gt;
&lt;p&gt;The main goal of this article is to present the core ideas behind implementing a DBMS, along with a bonus that gives a simplified explanation of how SQLite was implemented&lt;/p&gt;
&lt;h2&gt;Data comes and goes. But what does it represent?&lt;/h2&gt;
&lt;p&gt;Before understanding what happens during the execution of a DBMS, we need to understand what data is&lt;/p&gt;
&lt;p&gt;Data can be understood conceptually or physically&lt;/p&gt;
&lt;p&gt;A &lt;strong&gt;conceptual data&lt;/strong&gt; is an isolated set of qualitative or quantitative values For example, in a shopping list, the expressions &lt;em&gt;3&lt;/em&gt; and &lt;em&gt;lettuce&lt;/em&gt; are data The combination of this data can generate information, such as &amp;quot;buy 3 lettuce leaves&amp;quot;&lt;/p&gt;
&lt;p&gt;When we talk about &lt;strong&gt;physical data&lt;/strong&gt;, on the other hand, we are referring to any sequence of bytes that represents a conceptual data For example, using UTF-8 binary encoding, we can represent the expression &lt;em&gt;lettuce&lt;/em&gt; as the hexadecimal sequence &lt;em&gt;6C 65 74 74 75 63 65&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In the context of DBMSs, data is represented physically, since it is stored in &lt;strong&gt;storage devices&lt;/strong&gt; that only understand binary values&lt;/p&gt;
&lt;h2&gt;A bit about storage devices&lt;/h2&gt;
&lt;p&gt;Physical data is stored in storage devices, which are hardware specialized in storing, searching for, and retrieving bytes&lt;/p&gt;
&lt;p&gt;Examples of these devices are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;HD&lt;/em&gt; (Hard disk)&lt;/li&gt;
&lt;li&gt;&lt;em&gt;RAM&lt;/em&gt; (Random Access Memory)&lt;/li&gt;
&lt;li&gt;&lt;em&gt;SSD&lt;/em&gt; (Solid-state drive)&lt;/li&gt;
&lt;li&gt;&lt;em&gt;DVD&lt;/em&gt; (Digital versatile disk)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each device has a unique way of managing these bytes, whether through electrical charge (SSD), magnetism (HD), light sensitivity (DVD), or any other physical medium&lt;/p&gt;
&lt;p&gt;These devices can be &lt;strong&gt;volatile&lt;/strong&gt; or &lt;strong&gt;non-volatile&lt;/strong&gt; Volatile devices, unlike non-volatile ones, need power to keep the stored data This means that if, for example, we turn off the server, all its data will be lost RAM is a volatile device, while HD, SSD, and DVD are non-volatile&lt;/p&gt;
&lt;h2&gt;They&#39;re all the same, yet different…&lt;/h2&gt;
&lt;p&gt;From the very definition given earlier about a DBMS, we can conclude that all DBMSs have in common the storage of physical data in storage devices&lt;/p&gt;
&lt;p&gt;However, there are big differences between each of them, ranging from the data model (relational, document-oriented, …) to the type of storage device used (volatile or non-volatile)&lt;/p&gt;
&lt;p&gt;The first step to learning how to build a DBMS is to understand that, as different as the purposes of &lt;em&gt;MySQL&lt;/em&gt;, &lt;em&gt;MongoDB&lt;/em&gt;, and &lt;em&gt;Redis&lt;/em&gt; may be, all of them are based on storing physical data&lt;/p&gt;
&lt;h2&gt;And where does the operating system come into this story?&lt;/h2&gt;
&lt;p&gt;Although it might seem like DBMSs access storage devices directly, it is actually the operating system that does so&lt;/p&gt;
&lt;p&gt;This happens because of the extent and complexity of interacting with this hardware Imagine you wanted to implement a DBMS and, to do so, needed to understand how to communicate with a specific device through the memory bus Hard, right?&lt;/p&gt;
&lt;p&gt;The operating system is a facilitator It provides ways for us to communicate indirectly with these devices through system calls (syscalls)&lt;/p&gt;
&lt;p&gt;The way this communication happens is through &lt;strong&gt;file systems&lt;/strong&gt;, which will be explained in the next topic&lt;/p&gt;
&lt;h2&gt;Systems of what!?&lt;/h2&gt;
&lt;p&gt;File systems are an abstraction offered by the operating system to communicate with storage devices without having to access the hardware directly&lt;/p&gt;
&lt;p&gt;Each file represents a set of bytes stored on a device (such as an HD) Files have identifiers (usually names) and can generally be searched through a directory tree&lt;/p&gt;
&lt;p&gt;When we use a programming language to modify a file, under the hood we are accessing data on a storage device&lt;/p&gt;
&lt;p&gt;The second step to learning how to build a DBMS is understanding that it uses files (usually binary) as the fundamental basis for data management&lt;/p&gt;
&lt;p&gt;However, one caveat should be made When we talk about DBMSs that use memory (RAM) for data storage (as Redis does), we don&#39;t necessarily need to use files We can simply create data structures such as arrays or linked lists for temporary storage&lt;/p&gt;
&lt;p&gt;For the sake of simplicity, let&#39;s assume until the end of this article that the only abstraction used by DBMSs is the file system&lt;/p&gt;
&lt;h2&gt;A bit about files…&lt;/h2&gt;
&lt;p&gt;As mentioned earlier, a file is nothing more than a set of bytes located on some storage device&lt;/p&gt;
&lt;p&gt;Accessing a file is usually relatively slow This is because we need to make a system call to the operating system, which must retrieve the data contained in that file from the hardware For example, for an HD, there is a read-write arm that needs to move to find the file&#39;s bytes, which is a slow operation&lt;/p&gt;
&lt;p&gt;It&#39;s expected that byte organization should be optimized so we can insert, remove, and search for specific data with the fewest possible file accesses&lt;/p&gt;
&lt;p&gt;There are many ways to organize data in a file, and this organization is one of the points that can differ from one DBMS to another&lt;/p&gt;
&lt;p&gt;Examples of byte organization in a file include B+ trees and hash tables Although we usually think of these data structures only in memory (RAM), we can also represent and serialize them in a file&lt;/p&gt;
&lt;h2&gt;I trust the storage engine&lt;/h2&gt;
&lt;p&gt;DBMSs can be split into different modules, where each module is responsible for a specific functionality We can have a module that performs parsing on a query language (such as SQL), another that optimizes queries, another that interacts with files, and so on&lt;/p&gt;
&lt;p&gt;The module that interacts with files and defines how data is organized in those files is called the &lt;strong&gt;storage engine&lt;/strong&gt; (also known as &lt;em&gt;database engine&lt;/em&gt;)&lt;/p&gt;
&lt;p&gt;Examples of storage engines include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://dev.mysql.com/doc/refman/en/innodb-storage-engine.html&quot;&gt;InnoDB&lt;/a&gt; (used by default in MySQL)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/basho/bitcask&quot;&gt;Bitcask&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/TileDB-Inc/TileDB&quot;&gt;TileDB&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/PumpkinDB/PumpkinDB&quot;&gt;PumpkinDB&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Of all the modules a DBMS can provide, the storage engine is one of the most important, since without it we would have no way to store and retrieve data on devices&lt;/p&gt;
&lt;h2&gt;Performing operations on files&lt;/h2&gt;
&lt;p&gt;Understanding how we can, through code, access and manipulate bytes in a file is essential for analyzing how storage engines are implemented&lt;/p&gt;
&lt;p&gt;As mentioned earlier, files are abstractions provided by the operating system for manipulating bytes on a storage device without having to access it directly&lt;/p&gt;
&lt;p&gt;The operating system provides us with several operations that can be performed on files Examples of these operations include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Creation&lt;/em&gt;: Creates a new file&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Removal&lt;/em&gt;: Removes a file&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Read&lt;/em&gt;: Reads a fixed amount of bytes&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Write&lt;/em&gt;: Writes a sequence of bytes&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Seek&lt;/em&gt;: Searches for a specific byte&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For teaching purposes, we can understand a file as an array of bytes Each index of this array is called an &lt;strong&gt;offset&lt;/strong&gt;, and holds a single associated byte&lt;/p&gt;
&lt;p&gt;The file also has what we call a &lt;strong&gt;file cursor&lt;/strong&gt; (or file pointer), which is a fundamental concept for file manipulation It represents the current read or write position within a file&lt;/p&gt;
&lt;p&gt;For example, if we have a file with 100 bytes, with the current position at offset 0 (the first byte of the file), and we read 10 bytes, then the cursor moves to offset 10 (the eleventh byte of the file) If, from that position, we write another 10 bytes, the cursor then moves to offset 20&lt;/p&gt;
&lt;p&gt;We can also seek a specific offset, which means we will be changing the cursor&#39;s position This operation is usually costly, since the operating system needs to locate where that offset is on the storage device&lt;/p&gt;
&lt;p&gt;Programming languages are responsible for providing an interface that communicates with the operating system for file manipulation For example, the C language provides the &lt;a href=&quot;https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/fread&quot;&gt;&lt;em&gt;fread&lt;/em&gt;&lt;/a&gt;, &lt;a href=&quot;https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/fwrite&quot;&gt;&lt;em&gt;fwrite&lt;/em&gt;&lt;/a&gt;, and &lt;a href=&quot;https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/fseek&quot;&gt;&lt;em&gt;fseek&lt;/em&gt;&lt;/a&gt; functions to read, write, and seek bytes in a file, respectively The Java language, through the &lt;a href=&quot;https://docs.oracle.com/javase/7/docs/api//java/io/RandomAccessFile.html&quot;&gt;&lt;em&gt;RandomAccessFile&lt;/em&gt;&lt;/a&gt; class, provides the &lt;em&gt;read&lt;/em&gt;, &lt;em&gt;write&lt;/em&gt;, and &lt;em&gt;seek&lt;/em&gt; methods&lt;/p&gt;
&lt;h2&gt;Unveiling records and blocks&lt;/h2&gt;
&lt;p&gt;So far, we&#39;ve only discussed sequences of bytes in files, but we haven&#39;t covered how these bytes actually represent conceptual data&lt;/p&gt;
&lt;p&gt;Two concepts that can be found in storage engine implementations are records and blocks&lt;/p&gt;
&lt;p&gt;A &lt;strong&gt;record&lt;/strong&gt; within a binary file is a sequence of bytes that represents different fields with different types and values The concept of a record is normally used in relational DBMSs&lt;/p&gt;
&lt;p&gt;An example of a record with the fields &lt;em&gt;name&lt;/em&gt; and &lt;em&gt;favorite food&lt;/em&gt; is the byte sequence (in hexadecimal) &lt;em&gt;74 68 61 69 73 74 6F 6D 61 74 65&lt;/em&gt;, which can be deserialized into the values &lt;em&gt;thais&lt;/em&gt; and &lt;em&gt;tomato&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;There are several techniques for serializing and deserializing bytes into conceptual data One of them is &lt;a href=&quot;https://github.com/protocolbuffers/protobuf&quot;&gt;Protocol Buffers&lt;/a&gt;, a format used by Google for communication between different services, but which can also be used for storage in files Another format, specific to the Go programming language, is provided in the &lt;a href=&quot;https://pkg.go.dev/encoding/gob&quot;&gt;encoding/gob&lt;/a&gt; package&lt;/p&gt;
&lt;p&gt;A &lt;strong&gt;block&lt;/strong&gt; within a binary file is a fixed-size sequence of bytes that stores one or more data records Reading binary files can be done in blocks instead of individual bytes, increasing the number of records retrieved in a single read&lt;/p&gt;
&lt;p&gt;In some storage engines, a block represents a node (or page) of a B+ tree, as happens in SQLite&lt;/p&gt;
&lt;p&gt;Note that records and blocks are just techniques used for managing data in binary files, and are not necessarily mandatory There are several storage engine implementations, and each one can follow a different approach&lt;/p&gt;
&lt;h2&gt;A bit about data models…&lt;/h2&gt;
&lt;p&gt;Now that we understand how data is managed at the lowest level by a DBMS, we can abstract the discussion a bit&lt;/p&gt;
&lt;p&gt;Data models are theoretical models created for working with conceptual data following some defined system&lt;/p&gt;
&lt;p&gt;Examples of data models include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Relational&lt;/li&gt;
&lt;li&gt;Document-oriented&lt;/li&gt;
&lt;li&gt;Graph-oriented&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When implementing a DBMS, one of the first decisions that must be made is choosing which model or models the DBMS will follow&lt;/p&gt;
&lt;p&gt;DBMSs like PostgreSQL and MySQL follow the relational model, where data is represented by rows and columns in a table, and these tables can relate to each other&lt;/p&gt;
&lt;p&gt;Under the hood, we are still dealing with bytes in files, but what differentiates one data model from another is how these bytes are represented&lt;/p&gt;
&lt;h2&gt;Other DBMS modules&lt;/h2&gt;
&lt;p&gt;Earlier, we talked about the storage engine, which is a DBMS module responsible for managing data on a storage device&lt;/p&gt;
&lt;p&gt;There are several other modules a DBMS can implement&lt;/p&gt;
&lt;p&gt;Examples of other modules include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Compiler&lt;/em&gt;: When the DBMS uses a language such as SQL to perform queries, a compiler is essential for interpreting these queries&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Optimizer&lt;/em&gt;: Responsible for optimizing any query made to the DBMS, which may include creating equivalent queries and choosing algorithms to access the data&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Interface&lt;/em&gt;: Some DBMSs provide an interface (command line or any other means) to interact with different functionalities&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Driver&lt;/em&gt;: A driver allows a programming language to interact with different DBMS functionalities&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A DBMS usually contains several other modules to ensure its operation An in-depth explanation of each module is beyond the scope of this article&lt;/p&gt;
&lt;h2&gt;Bonus: How was SQLite implemented?&lt;/h2&gt;
&lt;p&gt;SQLite is a relational DBMS created with the C programming language All data is stored in a single binary file structured with multiple B+ trees, each representing a table or index&lt;/p&gt;
&lt;p&gt;The first bytes of the file contain metadata about the database, which assist in different operations SQLite performs on the file&lt;/p&gt;
&lt;p&gt;Fortunately, SQLite&#39;s source code is public domain and can be seen at &lt;a href=&quot;https://github.com/sqlite/sqlite&quot;&gt;github.com/sqlite/sqlite&lt;/a&gt; If you want to dig deeper into the file&#39;s binary format, the official website also provides a detailed explanation that can be accessed &lt;a href=&quot;https://www.sqlite.org/fileformat.html&quot;&gt;at this link&lt;/a&gt;&lt;/p&gt;
</content>
  </entry>
</feed>