<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Cheatsheet on Clément Joly – Open-Source, Rust &amp; SQLite</title><link>https://joly.pw/tags/cheatsheet/</link><description>Recent content in Cheatsheet on Clément Joly – Open-Source, Rust &amp; SQLite</description><image><title>Clément Joly – Open-Source, Rust &amp; SQLite</title><url>https://joly.pw/images/open-graph-pages.jpg</url><link>https://joly.pw/images/open-graph-pages.jpg</link></image><generator>Hugo</generator><language>en</language><copyright>Clément Joly</copyright><lastBuildDate>Thu, 28 May 2026 23:48:29 +0000</lastBuildDate><atom:link href="https://joly.pw/tags/cheatsheet/index.xml" rel="self" type="application/rss+xml"/><item><title>Vim Registers</title><link>https://joly.pw/reg/</link><pubDate>Thu, 29 Jan 2026 14:05:41 +0000</pubDate><guid>https://joly.pw/reg/</guid><description>A quirky but powerful feature.</description><content:encoded><![CDATA[<h2 id="copy-paste-history">Copy-paste History</h2>
<h3 id="implicit">Implicit</h3>
<table>
  <thead>
      <tr>
          <th style="text-align: center">Register</th>
          <th>Content</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td style="text-align: center"><code>&quot;</code></td>
          <td>Effectively last used register. Writes to register <code>0</code>.</td>
      </tr>
      <tr>
          <td style="text-align: center"><code>0</code></td>
          <td>Last yank.</td>
      </tr>
      <tr>
          <td style="text-align: center"><code>1</code></td>
          <td><code>d</code>/<code>c</code> with <code>%</code>,<code>(</code>, <code>)</code>, <code>`</code>, <code>/</code>, <code>?</code>, <code>n</code>, <code>N</code>, <code>{</code> and <code>}</code> or whole line.</td>
      </tr>
      <tr>
          <td style="text-align: center"><code>-</code></td>
          <td>Last small delete (less than a line). Can be the same as <code>1</code>.</td>
      </tr>
      <tr>
          <td style="text-align: center"><code>2</code>-<code>9</code></td>
          <td>Last content of <code>1</code>, <code>2</code>, etc. <code>9</code> is lost.</td>
      </tr>
      <tr>
          <td style="text-align: center"><code>+</code> <code>*</code></td>
          <td>System clipboards (X11/Wayland clipboard and primary).</td>
      </tr>
  </tbody>
</table>
<h3 id="explicit">Explicit</h3>
<table>
  <thead>
      <tr>
          <th style="text-align: center">Register</th>
          <th>Content</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td style="text-align: center"><code>a</code>-<code>z</code></td>
          <td>Named, use freely. Doesn’t fill numbered registers.</td>
      </tr>
      <tr>
          <td style="text-align: center"><code>A</code>-<code>Z</code></td>
          <td>Append to that named register.</td>
      </tr>
  </tbody>
</table>
<h2 id="read-only">Read-Only</h2>
<table>
  <thead>
      <tr>
          <th style="text-align: center">Register</th>
          <th>Content</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td style="text-align: center"><code>.</code></td>
          <td>Last inserted text (similar to <code>.</code> to repeat).</td>
      </tr>
      <tr>
          <td style="text-align: center"><code>%</code></td>
          <td>Current file name.</td>
      </tr>
      <tr>
          <td style="text-align: center"><code>#</code></td>
          <td>Alternate file name.</td>
      </tr>
      <tr>
          <td style="text-align: center"><code>:</code></td>
          <td>Last executed command line. Run with <code>@:</code>.</td>
      </tr>
  </tbody>
</table>
<h2 id="no-read-or-write">No Read or Write</h2>
<table>
  <thead>
      <tr>
          <th style="text-align: center">Register</th>
          <th>Content</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td style="text-align: center"><code>=</code></td>
          <td>Run an expression.</td>
      </tr>
      <tr>
          <td style="text-align: center"><code>_</code></td>
          <td>Black hole.</td>
      </tr>
  </tbody>
</table>
]]></content:encoded></item><item><title>SQLite Pragma Cheatsheet for Performance and Consistency</title><link>https://joly.pw/blog/sqlite-pragma-cheatsheet-for-performance-and-consistency/</link><pubDate>Fri, 07 May 2021 17:33:23 +0000</pubDate><guid>https://joly.pw/blog/sqlite-pragma-cheatsheet-for-performance-and-consistency/</guid><description>Last updated: March 18, 2024.</description><content:encoded><![CDATA[



  
  
  
  

  <div class="alert alert-tldr">
    <p class="alert-heading">
      ⚡
      
        TL;DR
      
    </p>
    <h3 id="when-opening-the-db">When Opening the DB</h3>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#e06c75">PRAGMA</span> <span style="color:#e06c75">journal_mode</span> <span style="color:#56b6c2">=</span> <span style="color:#e06c75">wal</span>; <span style="color:#7f848e">-- different implementation of the atomicity properties
</span></span></span><span style="display:flex;"><span><span style="color:#e06c75">PRAGMA</span> <span style="color:#e06c75">synchronous</span> <span style="color:#56b6c2">=</span> <span style="color:#e06c75">normal</span>; <span style="color:#7f848e">-- synchronise less often to the filesystem
</span></span></span><span style="display:flex;"><span><span style="color:#e06c75">PRAGMA</span> <span style="color:#e06c75">foreign_keys</span> <span style="color:#56b6c2">=</span> <span style="color:#c678dd">on</span>; <span style="color:#7f848e">-- check foreign key reference, slightly worst performance
</span></span></span></code></pre></div><p>And check <code>user_version</code> to apply any migrations, for instance with this <a href="https://joly.pw/rusqlite_migration/">Rust library</a>.</p>
<h3 id="when-closing-the-db">When Closing the DB</h3>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#e06c75">PRAGMA</span> <span style="color:#e06c75">analysis_limit</span><span style="color:#56b6c2">=</span><span style="color:#d19a66">400</span>; <span style="color:#7f848e">-- make sure pragma optimize does not take too long
</span></span></span><span style="display:flex;"><span><span style="color:#e06c75">PRAGMA</span> <span style="color:#e06c75">optimize</span>; <span style="color:#7f848e">-- gather statistics to improve query optimization
</span></span></span></code></pre></div>
  </div>



<h2 id="introduction">Introduction</h2>
<p>SQL pragma are statements (like <code>SELECT …</code> or <code>CREATE TABLE …</code>) that change the database behaviors or call a special functions. This post is a short list of <a href="https://sqlite.org">SQLite</a> pragma I use in my projects built on SQLite, to get better performance and more consistency.</p>
<h2 id="performance">Performance</h2>
<h3 id="file-system-interactions">File system Interactions</h3>
<p>The following pragma statements set the way SQLite deals with the file system.</p>
<h4 id="journal_mode-wal">journal_mode wal</h4>
<p>By default, when applying changes, SQLite uses a rollback journal, which is basically a copy of the data before the changes. Changing the <a href="https://sqlite.org/pragma.html#pragma_journal_mode">journal mode</a> to “Write-Ahead Log” is known to bring significantly better performance in most cases. It also allows concurrent readers with one writer. To activate it, run:</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#e06c75">PRAGMA</span> <span style="color:#e06c75">journal_mode</span> <span style="color:#56b6c2">=</span> <span style="color:#e06c75">wal</span>;
</span></span></code></pre></div><p>Some less common use cases are incompatible with this journal mode, for instance having a database on a network file system. The full list of drawbacks is <a href="https://sqlite.org/wal.html">listed in the documentation</a><sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>.</p>
<h4 id="synchronous-normal">synchronous normal</h4>
<p>To ensure integrity of the database, one of the mechanism SQLite uses is the file system synchronization operations. However, these synchronizations are quite costly. With WAL journal mode enabled, your database will still be consistent while synchronizing less often:</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#e06c75">PRAGMA</span> <span style="color:#e06c75">synchronous</span> <span style="color:#56b6c2">=</span> <span style="color:#e06c75">normal</span>;
</span></span></code></pre></div><p>Compared to the default <a href="https://sqlite.org/pragma.html#pragma_synchronous"><code>synchronous = full</code></a>, committed transactions could be rolled back if there is a power loss (although not if the application crashes).</p>
<h3 id="optimize">Optimize</h3>
<p>To execute statement as efficiently as possible, SQLite has a <a href="https://sqlite.org/queryplanner.html">query planner</a>, which tries to read the tables to provide good performance (for instance by evaluating the <code>WHERE</code> clauses that select the fewest rows first).</p>
<p>This query planner sometimes needs to know whether a column has many values or only a few, repeated values (like a boolean column would). To know this, it can’t read the whole table, as that may prove as costly as running the part of the query that is being optimized, so it uses some statistics collected in internal tables.</p>
<p>Using <a href="https://sqlite.org/pragma.html#pragma_optimize">optimize</a> right before closing the database connexion collects the statistics for some table columns. These columns are chosen mainly based on the queries executed during the connexion: if a query had benefited from more accurate statistics, the corresponding columns are analyzed.</p>
<p>For instance:</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#e06c75">PRAGMA</span> <span style="color:#e06c75">analysis_limit</span><span style="color:#56b6c2">=</span><span style="color:#d19a66">400</span>;
</span></span><span style="display:flex;"><span><span style="color:#e06c75">PRAGMA</span> <span style="color:#e06c75">optimize</span>;
</span></span></code></pre></div><p>In the above example, pragma <a href="https://sqlite.org/pragma.html#pragma_analysis_limit">analysis_limit</a> ensures that <code>optimize</code> won’t run for too long, by limiting the number of rows read.</p>
<h3 id="allow-using-more-memory">Allow Using More Memory</h3>
<p>These two pragma <em>could</em> result in better performance, depending on your hardware and software configuration.</p>
<ul>
<li>Keep temporary storage in memory: <a href="https://sqlite.org/pragma.html#pragma_temp_store"><code>PRAGMA temp_store = 2</code></a>. However, setting this pragma does not guarantee that the temporary storage will be held in memory. Please refer to the documentation for other parameters that may change the final outcome.</li>
<li>Keep more of the database pages in memory: for instance, use 32 MiB of memory for this purpose with <a href="https://sqlite.org/pragma.html#pragma_cache_size"><code>PRAGMA cache_size = -32000</code></a>. Note that the OS cache is already keeping parts of the database file in RAM, so this might end up wasting memory.</li>
</ul>
<h2 id="consistency">Consistency</h2>
<h3 id="user_version">user_version</h3>
<p>The database&rsquo;s schema can evolve over time. Your application could start with a <code>car</code> table to represent a car but later on, you realize you want to represent bicycles, so you add a <code>bicycle</code> table.</p>
<p>To keep track of the different versions of the schema, some libraries maintain an internal table with a single row with a version number. It then performs migrations as needed. In our example, version 1 would have only the <code>car</code> table and version 2, also the <code>bicycle</code> table. The migration from version 1 to version 2 add the <code>bicycle</code> table.</p>
<p>SQLite offers the <a href="https://sqlite.org/pragma.html#pragma_user_version">user_version</a> pragma, to keep track of these versions. It is an integer <a href="https://sqlite.org/fileformat2.html#user_version_number">at a fixed offset</a> in the database file. It is simpler and more efficient than maintaining a table with versions, in particular because the table has to be found in the database file while the integer is available right away.</p>
<p>The drawback is that this is not portable between database engines. If you only use SQLite though, it is almost always the best option. To use it, you can write some code to check the value of the <code>user_version</code> pragma value right after opening the database. If it is lower than expected, then atomically 1) run the necessary migrations and 2) increment the <code>user_version</code> pragma value. I wrote a library to ease this task in <a href="https://joly.pw/rusqlite_migration/">rust</a> and here is an <a href="https://levlaz.org/sqlite-db-migrations-with-pragma-user_version/">example in python</a>.</p>
<h3 id="foreign_keys-on">foreign_keys on</h3>
<p>This may come as a surprise for folks with experience with other database system, but SQLite does not enforce foreign key constraints by default. Consequently, a foreign key can point to a row that does not exist.</p>
<p>This can be fixed with pragma <a href="https://sqlite.org/pragma.html#pragma_foreign_keys">foreign_keys</a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#e06c75">PRAGMA</span> <span style="color:#e06c75">foreign_keys</span> <span style="color:#56b6c2">=</span> <span style="color:#c678dd">ON</span>;
</span></span></code></pre></div><p>This comes at a performance cost however, because more checks are performed when inserting values with foreign keys. The cost is usually negligible but your mileage may vary.</p>
<p><em>Note</em>: pragma <a href="https://sqlite.org/pragma.html#pragma_foreign_key_check">foreign_key_check</a> can be used to check a particular table for violated foreign key constraint. This can be useful before enabling <code>foreign_keys</code> on a database with existing data.</p>
<h3 id="strict">STRICT</h3>




  
  
  
  

  <div class="alert alert-important">
    <p class="alert-heading">
      🟣
      
        Important
      
    </p>
    <p>Requires SQLite version <a href="https://www.sqlite.org/releaselog/3_37_1.html">3.37.0 (2021-11-27)</a></p>
  </div>



<p>Another peculiarity of SQLite is dynamic typing through <a href="https://www.sqlite.org/datatype3.html">type affinity</a>. When you define a column of type <code>INTEGER</code> in most other database engines, a value of type <code>TEXT</code> inserted in that column will be converted or return an error. But with SQLite, type <a href="https://www.sqlite.org/datatype3.html#type_affinity">affinities</a> mean that if the value is not of the expected type, it will be converted if possible or stored with a different type if necessary. That’s handy when prototyping, but you may want a stricter behavior for consistency with other major SQL databases or when working with strictly typed languages.</p>
<p>To this end, SQLite supports the <a href="https://www.sqlite.org/stricttables.html">STRICT</a> keyword at table creation. For instance, if a table <code>t</code> is created like so:</p>
<pre tabindex="0"><code>CREATE TABLE t(a INTEGER) STRICT;
</code></pre><p>then</p>
<pre tabindex="0"><code>INSERT INTO t VALUES(1);
INSERT INTO t VALUES(&#39;1&#39;);
</code></pre><p>are successful but</p>
<pre tabindex="0"><code>INSERT INTO t VALUES(&#39;f&#39;);
</code></pre><p>is not and returns <code>Runtime error: cannot store TEXT value in INTEGER column t.a (19)</code>.</p>
<p><strong>Note</strong>: Without the <code>STRICT</code> keyword at table creation, this last <code>INSERT INTO …</code> statement would have been successful and would have just returned a string.</p>
<h2 id="go-deeper">Go deeper</h2>
<p>The full list of supported pragma with detailed descriptions is available in the <a href="https://sqlite.org/pragma.html">documentation</a>. Some <a href="https://kerkour.com/sqlite-for-servers">more options</a> can be tweaked for the specific scenario of running a SQLite for a server.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>A significant improvement to WAL mode is <a href="https://www.sqlite.org/cgi/src/doc/wal2/doc/wal2.md">being developped</a>, where the WAL file won’t grow to unbound sizes.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item></channel></rss>