<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Performance on Ivan Luminaria</title><link>https://ivanluminaria.com/it/tags/performance/</link><description>Recent content in Performance on Ivan Luminaria</description><generator>Hugo</generator><language>it</language><lastBuildDate>Tue, 24 Mar 2026 08:03:00 +0100</lastBuildDate><atom:link href="https://ivanluminaria.com/it/tags/performance/index.xml" rel="self" type="application/rss+xml"/><item><title>VACUUM e autovacuum: perché PostgreSQL ha bisogno che qualcuno pulisca</title><link>https://ivanluminaria.com/it/posts/postgresql/vacuum-autovacuum-postgresql/</link><pubDate>Tue, 24 Mar 2026 08:03:00 +0100</pubDate><guid>https://ivanluminaria.com/it/posts/postgresql/vacuum-autovacuum-postgresql/</guid><description>&lt;p&gt;Un paio d&amp;rsquo;anni fa mi chiedono di guardare un PostgreSQL in produzione che
&amp;ldquo;rallenta ogni settimana&amp;rdquo;. Sempre lo stesso pattern: lunedì va bene,
venerdì è un disastro. Il weekend qualcuno riavvia il servizio e si
ricomincia.&lt;/p&gt;
&lt;p&gt;Database da circa 200 GB. Tabelle principali che occupavano quasi il
triplo dello spazio effettivo dei dati. Query che andavano in sequential
scan su tabelle dove non avrebbero dovuto. Tempi di risposta che
salivano di giorno in giorno.&lt;/p&gt;</description></item><item><title>Oracle su Linux: i parametri kernel che nessuno configura</title><link>https://ivanluminaria.com/it/posts/oracle/oracle-linux-kernel/</link><pubDate>Tue, 24 Feb 2026 08:03:00 +0100</pubDate><guid>https://ivanluminaria.com/it/posts/oracle/oracle-linux-kernel/</guid><description>&lt;p&gt;Il cliente era una società di logistica con un Oracle 19c Enterprise Edition su Oracle Linux 8. Sessanta utenti concorrenti, un gestionale custom, circa 400 GB di dati. Il server era un Dell PowerEdge con 128 GB di RAM e 32 core.&lt;/p&gt;
&lt;p&gt;Le lamentele erano vaghe ma persistenti: &amp;ldquo;Il sistema è lento.&amp;rdquo; &amp;ldquo;Le query del mattino ci mettono il doppio rispetto a due mesi fa.&amp;rdquo; &amp;ldquo;Ogni tanto si blocca tutto per qualche secondo.&amp;rdquo;&lt;/p&gt;</description></item><item><title>AWR, ASH e i 10 minuti che hanno salvato un go-live</title><link>https://ivanluminaria.com/it/posts/oracle/oracle-awr-ash/</link><pubDate>Tue, 10 Feb 2026 08:03:00 +0100</pubDate><guid>https://ivanluminaria.com/it/posts/oracle/oracle-awr-ash/</guid><description>&lt;p&gt;Venerdì, ore 18:40. Ero già con il giubbotto addosso, pronto per uscire. Il telefono vibra. È il project manager.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Ivan, abbiamo un problema. Il sistema è lentissimo. Domani mattina c&amp;rsquo;è il go-live.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Non è la prima volta che ricevo una chiamata del genere. Ma il tono era diverso dal solito. Non era la lamentela generica sulla lentezza. Era panico.&lt;/p&gt;
&lt;p&gt;Mi ricollego in VPN, apro una sessione sul database Oracle 19c del cliente. La prima cosa che faccio è un controllo rapido:&lt;/p&gt;</description></item><item><title>Quando un LIKE '%valore%' rallenta tutto: un caso reale di ottimizzazione PostgreSQL</title><link>https://ivanluminaria.com/it/posts/postgresql/like-optimization-postgresql/</link><pubDate>Tue, 06 Jan 2026 08:03:00 +0100</pubDate><guid>https://ivanluminaria.com/it/posts/postgresql/like-optimization-postgresql/</guid><description>&lt;p&gt;Qualche settimana fa un cliente mi contatta con un problema molto
comune:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;La ricerca nella console amministrativa è lenta. A volte impiega
diversi secondi. Abbiamo già ridotto le JOIN, ma il problema non è
sparito.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Ambiente: PostgreSQL su cloud managed.&lt;br&gt;
Tabella principale: &lt;code&gt;payment_report&lt;/code&gt; (~6 milioni di righe, 3 GB).&lt;br&gt;
Colonna ricercata: &lt;code&gt;reference_code&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Query incriminata:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;reporting&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;payment_report&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;JOIN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;reporting&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;payment_cart&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ON&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cart_id&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;service_id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1001&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AND&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reference_code&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;LIKE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;%ABC123%&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ORDER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;BY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;created_at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;DESC&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;LIMIT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="-prima-osservazione-il-problema-non-erano-le-join" class="relative group"&gt;🧠 Prima osservazione: il problema non erano le JOIN &lt;span class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100"&gt;&lt;a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700" style="text-decoration-line: none !important;" href="#-prima-osservazione-il-problema-non-erano-le-join" aria-label="Ancora"&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;Ho confrontato:&lt;/p&gt;</description></item><item><title>Oracle Partitioning: quando 2 miliardi di righe non entrano più in una query</title><link>https://ivanluminaria.com/it/posts/oracle/oracle-partitioning/</link><pubDate>Tue, 23 Dec 2025 08:03:00 +0100</pubDate><guid>https://ivanluminaria.com/it/posts/oracle/oracle-partitioning/</guid><description>&lt;p&gt;Due miliardi di righe. Non è un numero che si raggiunge in un giorno. Ci vogliono anni di transazioni, di movimenti, di registrazioni quotidiane che si accumulano. E per tutto quel tempo il database funziona, le query rispondono, i report escono. Poi un giorno qualcuno apre un ticket: &amp;ldquo;il report mensile ci mette quattro ore.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Quattro ore. Per un report che sei mesi prima ne impiegava venti minuti.&lt;/p&gt;
&lt;p&gt;Non è un bug. Non è un problema di rete o di storage lento. È la fisica dei dati: quando una tabella cresce oltre una certa soglia, gli approcci che funzionavano smettono di funzionare. E se non hai progettato la struttura per gestire quella crescita, il database fa l&amp;rsquo;unica cosa che può fare: leggere tutto.&lt;/p&gt;</description></item><item><title>EXPLAIN ANALYZE non basta: come leggere davvero un piano di esecuzione PostgreSQL</title><link>https://ivanluminaria.com/it/posts/postgresql/explain-analyze-postgresql/</link><pubDate>Tue, 28 Oct 2025 08:03:00 +0100</pubDate><guid>https://ivanluminaria.com/it/posts/postgresql/explain-analyze-postgresql/</guid><description>&lt;p&gt;L&amp;rsquo;altro giorno un collega mi manda uno screenshot su Teams. Una query che gira su una tabella da 2 milioni di righe, 45 secondi di esecuzione. Mi scrive:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Ho fatto EXPLAIN ANALYZE, ma non capisco cosa c&amp;rsquo;è che non va. Il piano sembra corretto.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Spoiler: il piano non era affatto corretto. L&amp;rsquo;optimizer aveva scelto un &lt;span class="glossary-tip" tabindex="0" data-glossary-desc="Nested Loop Join — strategia di join che scansiona la tabella interna per ogni riga della tabella esterna, ideale per dataset piccoli con indice." data-glossary-url="https://ivanluminaria.com/it/glossary/nested-loop/" data-glossary-more="Leggi di più →"&gt;nested loop&lt;/span&gt;
 join dove serviva un &lt;span class="glossary-tip" tabindex="0" data-glossary-desc="Hash Join — strategia di join ottimizzata per grandi volumi di dati, basata su una hash table costruita in memoria." data-glossary-url="https://ivanluminaria.com/it/glossary/hash-join/" data-glossary-more="Leggi di più →"&gt;hash join&lt;/span&gt;
, e la ragione era banale — statistiche non aggiornate. Ma per arrivarci ho dovuto leggere il piano riga per riga, e lì mi sono reso conto che la maggior parte dei DBA che conosco usa EXPLAIN ANALYZE come un oracolo binario: se il tempo è alto, la query è lenta. Fine dell&amp;rsquo;analisi.&lt;/p&gt;</description></item></channel></rss>