<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Performance &#8211; Other Things</title>
	<atom:link href="https://blog.adamzolo.com/category/performance/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.adamzolo.com</link>
	<description>Blog about Things by Adam Zolotarev</description>
	<lastBuildDate>Fri, 11 Feb 2022 14:24:32 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.1</generator>
	<item>
		<title>The Cost of PostgreSQL Foreign Keys</title>
		<link>https://blog.adamzolo.com/the-cost-of-postgresql-foreign-keys/</link>
					<comments>https://blog.adamzolo.com/the-cost-of-postgresql-foreign-keys/#respond</comments>
		
		<dc:creator><![CDATA[Adam Zolo]]></dc:creator>
		<pubDate>Thu, 10 Feb 2022 22:38:00 +0000</pubDate>
				<category><![CDATA[Performance]]></category>
		<category><![CDATA[SQL]]></category>
		<guid isPermaLink="false">https://blog.adamzolo.com/?p=998</guid>

					<description><![CDATA[Acknowledgments: shout out to Steven Jones at Syncro for helping me better understand how Foreign Keys work in PostgreSQL. Foreign keys are great for maintaining data integrity. However, they are not free. As mentioned in this blog post by Shaun Thomas: In PostgreSQL, every foreign key is maintained with an invisible system-level trigger added to&#8230;<p><a class="more-link" href="https://blog.adamzolo.com/the-cost-of-postgresql-foreign-keys/" title="Continue reading &#8216;The Cost of PostgreSQL Foreign Keys&#8217;">Continue reading <span class="meta-nav">&#8594;</span></a></p>]]></description>
										<content:encoded><![CDATA[
<p></p>



<p><strong>Acknowledgments</strong>: shout out to <a rel="noreferrer noopener" href="https://www.linkedin.com/in/steven-jones-a732567/" target="_blank">Steven Jones</a> at <a href="https://syncromsp.com/" target="_blank" rel="noreferrer noopener">Syncro</a> for helping me better understand how Foreign Keys work in PostgreSQL.</p>



<p></p>



<p>Foreign keys are great for maintaining data integrity. However, they are not free.</p>



<p>As mentioned in this blog post by Shaun Thomas:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>In PostgreSQL, every foreign key is maintained with an invisible system-level trigger added to the&nbsp;<em>source</em>&nbsp;table in the reference. At least one trigger must go here, as operations that modify the source data must be checked that they do not violate the constraint.</p><cite>https://bonesmoses.org/2014/05/14/foreign-keys-are-not-free/</cite></blockquote>



<p>What this means is that when you modify your parent table, even if you don&#8217;t touch any of the referred keys, these triggers are still fired. </p>



<p>In the original post from 2014, the overhead made the updates up to 95% slower with 20 foreign keys. Let&#8217;s see if things changed since then.</p>



<p></p>



<p>These are slightly updated scripts we&#8217;ll use for testing</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: sql; title: ; notranslate">
CREATE OR REPLACE FUNCTION fnc_create_check_fk_overhead(key_count INT)
RETURNS VOID AS
$$
DECLARE
  i INT;
BEGIN
  CREATE TABLE test_fk
  (
    id   BIGINT PRIMARY KEY,
    junk VARCHAR
  );

  INSERT INTO test_fk
  SELECT generate_series(1, 100000), repeat(&#039; &#039;, 20);

  CLUSTER test_fk_pkey ON test_fk;

  FOR i IN 1..key_count LOOP
    EXECUTE &#039;CREATE TABLE test_fk_ref_&#039; || i || 
            &#039; (test_fk_id BIGINT REFERENCES test_fk (id))&#039;;
						
  END LOOP;

END;
$$ LANGUAGE plpgsql VOLATILE;


CREATE OR REPLACE FUNCTION fnc_check_fk_overhead(key_count INT)
RETURNS VOID AS
$$
DECLARE
  i INT;
BEGIN
  FOR i IN 1..100000 LOOP
    UPDATE test_fk SET junk = &#039;    blah                &#039;
     WHERE id = i;
  END LOOP;

END;
$$ LANGUAGE plpgsql VOLATILE;


CREATE OR REPLACE FUNCTION clean_up_overhead(key_count INT)
RETURNS VOID AS
$$
DECLARE
  i INT;
BEGIN
  DROP TABLE test_fk CASCADE;

  FOR i IN 1..key_count LOOP
    EXECUTE &#039;DROP TABLE test_fk_ref_&#039; || i;
  END LOOP;
END;
$$ LANGUAGE plpgsql VOLATILE;
</pre></div>


<p>To validate that the overhead is caused strictly by the presence of the foreign keys, and not from the cost of looking up the child records, after the first benchmark, we&#8217;ll modify the first function and add indexes on each foreign key:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: sql; title: ; notranslate">
CREATE OR REPLACE FUNCTION fnc_create_check_fk_overhead(key_count INT)
RETURNS VOID AS
$$
DECLARE
  i INT;
BEGIN
  CREATE TABLE test_fk
  (
    id   BIGINT PRIMARY KEY,
    junk VARCHAR
  );

  INSERT INTO test_fk
  SELECT generate_series(1, 100000), repeat(&#039; &#039;, 20);

  CLUSTER test_fk_pkey ON test_fk;

  FOR i IN 1..key_count LOOP
    EXECUTE &#039;CREATE TABLE test_fk_ref_&#039; || i || 
            &#039; (test_fk_id BIGINT REFERENCES test_fk (id))&#039;;
						
		EXECUTE &#039;CREATE index test_fk_ref_index_&#039; || i ||
            &#039; on test_fk_ref_&#039; || i || &#039;(test_fk_id)&#039;;
  END LOOP;

END;
$$ LANGUAGE plpgsql VOLATILE;
</pre></div>


<p></p>



<p>We&#8217;ll run on on Mac i9, 2.3 GHz 8-Core, 64 GB Ram</p>



<p>PostgreSQL version 12</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: sql; title: ; notranslate">
-- without an index

select fnc_create_check_fk_overhead(0);
SELECT fnc_check_fk_overhead(0); -- 2.6-2.829
select clean_up_overhead(0)


select fnc_create_check_fk_overhead(20);
SELECT fnc_check_fk_overhead(20); -- 3.186-3.5. ~20% drop
select clean_up_overhead(20)


-- after updating our initial function to add an index for each foreign key:
select fnc_create_check_fk_overhead(0);
SELECT fnc_check_fk_overhead(0); -- 2.6-2.8
select clean_up_overhead(0)

select fnc_create_check_fk_overhead(20);
SELECT fnc_check_fk_overhead(20); -- 3.1 same ~20% drop
select clean_up_overhead(20)


</pre></div>


<p>As we see from the benchmark, the drop in update performance on a parent table is about 20% after adding 20 tables with a foreign key to the parent. It&#8217;s not quite as bad as <meta charset="utf-8">95% in the original post, but the overhead is still clearly there.</p>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.adamzolo.com/the-cost-of-postgresql-foreign-keys/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Improving Visual Studio Performance with RAM disk and Second SSD</title>
		<link>https://blog.adamzolo.com/improve-visual-studio-performance-ssd/</link>
					<comments>https://blog.adamzolo.com/improve-visual-studio-performance-ssd/#respond</comments>
		
		<dc:creator><![CDATA[Adam Zolo]]></dc:creator>
		<pubDate>Sat, 20 Sep 2014 16:08:22 +0000</pubDate>
				<category><![CDATA[Performance]]></category>
		<category><![CDATA[Visual Studio]]></category>
		<guid isPermaLink="false">http://eazolo.com/blog/?p=91</guid>

					<description><![CDATA[One of the best way to improve Visual Studio performance is to replace your HDD with SSD. However, for various reasons it may not always an option. Here are a few other hardware-related suggestions that may help your Visual Studio experience: If you have enough RAM, create a RAM disk (I use freeware from SoftPerfect&#8230;<p><a class="more-link" href="https://blog.adamzolo.com/improve-visual-studio-performance-ssd/" title="Continue reading &#8216;Improving Visual Studio Performance with RAM disk and Second SSD&#8217;">Continue reading <span class="meta-nav">&#8594;</span></a></p>]]></description>
										<content:encoded><![CDATA[<p>One of the best way to improve Visual Studio performance is to replace your HDD with SSD. However, for various reasons it may not always an option. Here are a few other hardware-related suggestions that may help your Visual Studio experience:</p>
<ul>
<li>If you have enough RAM, create a RAM disk (I use freeware from <a href="http://www.softperfect.com" title="SoftPerfect" target="_blank">SoftPerfect </a>). Set your web.config to use it as a temp compilation directory:
<pre class="brush: plain; title: ; notranslate">
 &lt;compilation tempDirectory=&quot;R:\TempAspFolderOnRamDisk&quot;&gt;
</pre>
<p>While you are there, you can experiment with batch parameter. It is used to control whether the initial page request will continue to compile additional files in the same directory before completing the original request. I prefer to set it to false.
</li>
<li>
If you have an ability to add a second SSD, you may want to move all your source code to it. However, it may mean you have to change the configuration on your machine to make it work on a different drive/folder. To avoid this configuration headache, instead create a symbolic link between your original source code directory, and the new one on the SSD drive:</p>
<pre class="brush: plain; title: ; notranslate">
mklink /D &quot;C:\originalSourceCodeDirectory&quot; R:\DirectoryOnSSD
</pre>
<p>You have to delete or rename the originalSourceCodeDirectory prior to running mklink command.
</li>
<li> Move your bin/obj folders to RamDisk. Use symbolic links to avoid configuration problems. This did not seem to have any noticeable effect on my configuration, but your mileage may vary.
</li>
</li>
<li>Use some caching software like <a href="http://www.romexsoftware.com/en-us/index.html" title="PrimoCache" target="_blank">PrimoCache</a>. It allows to cache data either to your RAM or an additional SSD.
</li>
</ul>
<p>The most beneficial of these techniques for me was moving source code to SSD.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.adamzolo.com/improve-visual-studio-performance-ssd/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
