<?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 Archives - Philipp Salvisberg&#039;s Blog</title>
	<atom:link href="https://www.salvis.com/blog/tag/performance/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.salvis.com/blog/tag/performance/</link>
	<description>Database-centric development</description>
	<lastBuildDate>Wed, 08 Nov 2023 09:55:47 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://www.salvis.com/blog/wp-content/uploads/2014/04/favicon.png</url>
	<title>Performance Archives - Philipp Salvisberg&#039;s Blog</title>
	<link>https://www.salvis.com/blog/tag/performance/</link>
	<width>32</width>
	<height>32</height>
</image> 
<atom:link rel="hub" href="https://pubsubhubbub.appspot.com"/>
<atom:link rel="hub" href="https://pubsubhubbub.superfeedr.com"/>
<atom:link rel="hub" href="https://websubhub.com/hub"/>
<atom:link rel="self" href="https://www.salvis.com/blog/tag/performance/feed/"/>
	<item>
		<title>Constants vs. Parameterless Functions</title>
		<link>https://www.salvis.com/blog/2019/12/13/constants-vs-parameterless-functions/</link>
					<comments>https://www.salvis.com/blog/2019/12/13/constants-vs-parameterless-functions/#comments</comments>
		
		<dc:creator><![CDATA[Philipp Salvisberg]]></dc:creator>
		<pubDate>Fri, 13 Dec 2019 17:24:17 +0000</pubDate>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[PL/SQL]]></category>
		<category><![CDATA[SQL]]></category>
		<guid isPermaLink="false">https://www.salvis.com/blog/?p=9417</guid>

					<description><![CDATA[<p>Do you use parameterless PL/SQL functions in your queries? Did you know that this may cause performance issues? In this blog post, I explain why parameterless functions can be the reason for bad execution plans in any Oracle Database. I recently had to analyze this problem in a production system and thought<span class="excerpt-hellip"> […]</span></p>
<p>The post <a href="https://www.salvis.com/blog/2019/12/13/constants-vs-parameterless-functions/">Constants vs. Parameterless Functions</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Do you use parameterless PL/SQL functions in your queries? Did you know that this may cause performance issues? In this blog post, I explain why parameterless functions can be the reason for bad execution plans in any Oracle Database.</p>



<figure class="wp-block-image"><a href="https://www.salvis.com/blog/wp-content/uploads/2019/12/bad_execution_plan.png"><img fetchpriority="high" decoding="async" width="686" height="360" src="https://www.salvis.com/blog/wp-content/uploads/2019/12/bad_execution_plan.png" alt="" class="wp-image-9432" srcset="https://www.salvis.com/blog/wp-content/uploads/2019/12/bad_execution_plan.png 686w, https://www.salvis.com/blog/wp-content/uploads/2019/12/bad_execution_plan-300x157.png 300w, https://www.salvis.com/blog/wp-content/uploads/2019/12/bad_execution_plan-260x136.png 260w, https://www.salvis.com/blog/wp-content/uploads/2019/12/bad_execution_plan-50x26.png 50w, https://www.salvis.com/blog/wp-content/uploads/2019/12/bad_execution_plan-143x75.png 143w" sizes="(max-width:767px) 480px, 686px" /></a></figure>



<p>I recently had to analyze this problem in a production system and thought it was worth sharing. On the one hand, because we did not find a satisfactory solution and on the other hand because this could change in the future when we start discussing it.</p>



<p>For this blog post, I used an Oracle Database 19c Enterprise Edition, version 19.5.0.0.0 in a Docker environment. However, you can run the scripts in any edition of an Oracle Database 12c Release 1 or later to reproduce the results.</p>



<h2 class="wp-block-heading">1. Data Setup</h2>



<p>We create a user <code>demo</code>&nbsp; with <code>ALTER SESSION</code> and <code>SELECT ANY DICTIONARY</code> privileges as follows:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Create user demo</span><span role="button" tabindex="0" data-code="CREATE USER demo IDENTIFIED BY demo  
DEFAULT TABLESPACE users
TEMPORARY TABLESPACE temp
QUOTA UNLIMITED ON users;

GRANT connect, resource TO demo;
GRANT alter session TO demo;
GRANT select any dictionary TO demo;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">CREATE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">USER</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">demo</span><span style="color: #D4D4D4"> IDENTIFIED </span><span style="color: #569CD6">BY</span><span style="color: #D4D4D4"> demo  </span></span>
<span class="line"><span style="color: #569CD6">DEFAULT</span><span style="color: #D4D4D4"> TABLESPACE users</span></span>
<span class="line"><span style="color: #D4D4D4">TEMPORARY TABLESPACE temp</span></span>
<span class="line"><span style="color: #D4D4D4">QUOTA </span><span style="color: #569CD6">UNLIMITED</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> users;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">GRANT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">connect</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">resource</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">TO</span><span style="color: #D4D4D4"> demo;</span></span>
<span class="line"><span style="color: #569CD6">GRANT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">alter</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">session</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">TO</span><span style="color: #D4D4D4"> demo;</span></span>
<span class="line"><span style="color: #569CD6">GRANT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> any dictionary </span><span style="color: #569CD6">TO</span><span style="color: #D4D4D4"> demo;</span></span></code></pre></div>



<p>Then as user <code>demo</code> we create a table <code>t</code> with an index <code>t_ind_idx</code> on column <code>ind</code></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Create table t</span><span role="button" tabindex="0" data-code="CREATE TABLE t (
   id   INTEGER       GENERATED ALWAYS AS IDENTITY CONSTRAINT t_pk PRIMARY KEY,
   ind  INTEGER       NOT NULL CONSTRAINT ind_ck CHECK (ind IN (0, 1)), 
   text VARCHAR2(100) NOT NULL
);
CREATE INDEX t_ind_idx ON t (ind);" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">CREATE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">TABLE</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">t</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">   id   </span><span style="color: #569CD6">INTEGER</span><span style="color: #D4D4D4">       </span><span style="color: #569CD6">GENERATED</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">ALWAYS</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">IDENTITY</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">CONSTRAINT</span><span style="color: #D4D4D4"> t_pk </span><span style="color: #569CD6">PRIMARY KEY</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">   ind  </span><span style="color: #569CD6">INTEGER</span><span style="color: #D4D4D4">       </span><span style="color: #569CD6">NOT NULL</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">CONSTRAINT</span><span style="color: #D4D4D4"> ind_ck </span><span style="color: #569CD6">CHECK</span><span style="color: #D4D4D4"> (ind </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">)), </span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">text</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VARCHAR2</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">100</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">NOT NULL</span></span>
<span class="line"><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #569CD6">CREATE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">INDEX</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">t_ind_idx</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> t (ind);</span></span></code></pre></div>



<p>and populated table <code>t</code> with the following anonymous PL/SQL block:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Populate table t</span><span role="button" tabindex="0" data-code="BEGIN
   dbms_random.seed(0);
   INSERT INTO t (ind, text)
   SELECT CASE 
             WHEN dbms_random.value(0, 999) < 1 THEN
                1 
             ELSE 
                0
          END AS ind,
          dbms_random.string('p', round(dbms_random.value(5, 100),0)) AS text
     FROM xmltable('1 to 100000');
   COMMIT;
END;
/" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">BEGIN</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #DCDCAA">dbms_random.</span><span style="color: #4EC9B0">seed</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">INSERT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">INTO</span><span style="color: #D4D4D4"> t (ind, text)</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> </span><span style="color: #C586C0">CASE</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">WHEN</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">dbms_random.</span><span style="color: #4EC9B0">value</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">999</span><span style="color: #D4D4D4">) &lt; </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">THEN</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #C586C0">ELSE</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #B5CEA8">0</span></span>
<span class="line"><span style="color: #D4D4D4">          </span><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> ind,</span></span>
<span class="line"><span style="color: #D4D4D4">          </span><span style="color: #DCDCAA">dbms_random.</span><span style="color: #4EC9B0">string</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&#39;p&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #DCDCAA">round</span><span style="color: #D4D4D4">(</span><span style="color: #DCDCAA">dbms_random.</span><span style="color: #4EC9B0">value</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">5</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">100</span><span style="color: #D4D4D4">),</span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">)) </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> text</span></span>
<span class="line"><span style="color: #D4D4D4">     </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">xmltable</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&#39;1 to 100000&#39;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #DCDCAA">COMMIT</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #569CD6">END</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">/</span></span></code></pre></div>



<p>The case expression leads to a skewed distribution of column <code>ind</code>. Only around 0.1% of the rows have a value <code>1</code> as the following query shows:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Distribution of column ind</span><span role="button" tabindex="0" data-code="SELECT ind, count(*) 
  FROM t 
 GROUP BY ind;

       IND   COUNT(*)
---------- ----------
         1        101
         0      99899" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> ind, </span><span style="color: #DCDCAA">count</span><span style="color: #D4D4D4">(*) </span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> t </span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">GROUP BY</span><span style="color: #D4D4D4"> ind;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">       IND   </span><span style="color: #DCDCAA">COUNT</span><span style="color: #D4D4D4">(*)</span></span>
<span class="line"><span style="color: #6A9955">---------- ----------</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">        </span><span style="color: #B5CEA8">101</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">      </span><span style="color: #B5CEA8">99899</span></span></code></pre></div>



<p>Therefore we are gathering statistics for table <code>t</code>&nbsp; with a histogram for column <code>ind</code>:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Gather statistics</span><span role="button" tabindex="0" data-code="BEGIN
   dbms_stats.gather_table_stats(
      ownname    =&gt; user, 
      tabname    =&gt; 'T', 
      method_opt =&gt; 'FOR ALL COLUMNS SIZE AUTO FOR COLUMNS SIZE 2 IND'
   );
END;
/" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">BEGIN</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #DCDCAA">dbms_stats.</span><span style="color: #4EC9B0">gather_table_stats</span><span style="color: #D4D4D4">(</span></span>
<span class="line"><span style="color: #D4D4D4">      ownname    =&gt; </span><span style="color: #DCDCAA">user</span><span style="color: #D4D4D4">, </span></span>
<span class="line"><span style="color: #D4D4D4">      tabname    =&gt; </span><span style="color: #CE9178">&#39;T&#39;</span><span style="color: #D4D4D4">, </span></span>
<span class="line"><span style="color: #D4D4D4">      method_opt =&gt; </span><span style="color: #CE9178">&#39;FOR ALL COLUMNS SIZE AUTO FOR COLUMNS SIZE 2 IND&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">   );</span></span>
<span class="line"><span style="color: #569CD6">END</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">/</span></span></code></pre></div>



<p>Now, we can check the histogram with the following query:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Histogramm of column ind</span><span role="button" tabindex="0" data-code="SELECT endpoint_value, endpoint_number 
  FROM user_histograms
 WHERE table_name = 'T' 
   AND column_name = 'IND';

ENDPOINT_VALUE ENDPOINT_NUMBER
-------------- ---------------
             0           99899
             1          100000" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> endpoint_value, endpoint_number </span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> user_histograms</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> table_name = </span><span style="color: #CE9178">&#39;T&#39;</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> column_name = </span><span style="color: #CE9178">&#39;IND&#39;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">ENDPOINT_VALUE ENDPOINT_NUMBER</span></span>
<span class="line"><span style="color: #6A9955">-------------- ---------------</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">           </span><span style="color: #B5CEA8">99899</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">          </span><span style="color: #B5CEA8">100000</span></span></code></pre></div>



<p>Two rows for the two values of column <code>ind</code>. For value <code>0</code> we expect 99899 rows (endpoints) and for value <code>1</code>&nbsp; we expect 101 rows (100000 &#8211; 99899 endpoints). This is 100 percent accurate.</p>



<h2 class="wp-block-heading">2. Constant Declaration</h2>



<p>In the <a href="https://trivadis.github.io/plsql-and-sql-coding-guidelines/v3.6/4-language-usage/1-general/g-1050/">Trivadis PL/SQL &amp; SQL Guidelines</a> we recommend avoiding the use of literals in PL/SQL code. Every time we see a literal in a PL/SQL code we should consider using a constant instead. Often this makes sense because the name of the constant is more meaningful than the literal, making the code more readable and maintainable.</p>



<p>Hence we create the following PL/SQL package for our representation of boolean values in SQL:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">PL/SQL package for boolean values</span><span role="button" tabindex="0" data-code="CREATE OR REPLACE PACKAGE const_boolean AUTHID DEFINER IS
   co_true  CONSTANT INTEGER := 1;
   co_false CONSTANT INTEGER := 0;
END const_boolean;
/" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">CREATE OR REPLACE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">PACKAGE</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">const_boolean</span><span style="color: #D4D4D4"> AUTHID DEFINER </span><span style="color: #569CD6">IS</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">   co_true  </span><span style="color: #569CD6">CONSTANT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">INTEGER</span><span style="color: #D4D4D4"> := </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">   co_false </span><span style="color: #569CD6">CONSTANT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">INTEGER</span><span style="color: #D4D4D4"> := </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> const_boolean;</span></span>
<span class="line"><span style="color: #D4D4D4">/</span></span></code></pre></div>



<p>Now we can use these constants in our PL/SQL code as follows:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">SQL using a constant (within PL/SQL)</span><span role="button" tabindex="0" data-code="SET SERVEROUTPUT ON
BEGIN
   FOR r IN (
      SELECT count(*) AS open_count
        FROM t 
       WHERE ind = const_boolean.co_true
   ) LOOP
      dbms_output.put_line('open: ' || r.open_count);
   END LOOP;
END;
/

open: 101

PL/SQL procedure successfully completed." style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">SET</span><span style="color: #D4D4D4"> SERVEROUTPUT </span><span style="color: #569CD6">ON</span></span>
<span class="line"><span style="color: #569CD6">BEGIN</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #C586C0">FOR</span><span style="color: #D4D4D4"> r </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">count</span><span style="color: #D4D4D4">(*) </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> open_count</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> t </span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> ind = const_boolean.co_true</span></span>
<span class="line"><span style="color: #D4D4D4">   ) </span><span style="color: #C586C0">LOOP</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #DCDCAA">dbms_output.</span><span style="color: #4EC9B0">put_line</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&#39;open: &#39;</span><span style="color: #D4D4D4"> || r.open_count);</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #C586C0">END LOOP</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #569CD6">END</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">/</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">open</span><span style="color: #D4D4D4">: </span><span style="color: #B5CEA8">101</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">PL/</span><span style="color: #569CD6">SQL</span><span style="color: #D4D4D4"> procedure successfully completed.</span></span></code></pre></div>



<p>When developing complex SQL statements I often run them standalone in an IDE until I&#8217;m satisfied with the result. But when we run this</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">SQL using a constant (outside of PL/SQL)</span><span role="button" tabindex="0" data-code="SELECT count(*) AS open_count
  FROM t 
 WHERE ind = const_boolean.co_true;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">count</span><span style="color: #D4D4D4">(*) </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> open_count</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> t </span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> ind = const_boolean.co_true;</span></span></code></pre></div>



<p>we get the following error message:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Error when using a constant in SQL</span><span role="button" tabindex="0" data-code="Error starting at line : 1 in command -
SELECT count(*) AS open_count
  FROM t 
 WHERE ind = const_boolean.co_true
Error at Command Line : 3 Column : 14
Error report -
SQL Error: ORA-06553: PLS-221: 'CO_TRUE' is not a procedure or is undefined
06553. 00000 -  &quot;PLS-%s: %s&quot;
*Cause:    
*Action:" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">Error starting at line : 1 in command -</span></span>
<span class="line"><span style="color: #D4D4D4">SELECT count(*) AS open_count</span></span>
<span class="line"><span style="color: #D4D4D4">  FROM t </span></span>
<span class="line"><span style="color: #D4D4D4"> WHERE ind = const_boolean.co_true</span></span>
<span class="line"><span style="color: #D4D4D4">Error at Command Line : 3 Column : 14</span></span>
<span class="line"><span style="color: #D4D4D4">Error report -</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">SQL Error: ORA-06553: PLS-221: &#39;CO_TRUE&#39; is not a procedure or is undefined</span></span>
<span class="line"><span style="color: #D4D4D4">06553. 00000 -  &quot;PLS-%s: %s&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">*Cause:    </span></span>
<span class="line"><span style="color: #D4D4D4">*Action:</span></span></code></pre></div>



<p>We have to change the constant <code>const_boolean.co_true</code>&nbsp; to a literal (<code>1</code>), which is cumbersome and error-prone.</p>



<h2 class="wp-block-heading">3. Parameterless Functions for Constants</h2>



<p>As a workaround, we can create a parameterless function for each constant. Like this:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Parameterless function for each constant</span><span role="button" tabindex="0" data-code="CREATE OR REPLACE PACKAGE const_boolean AUTHID DEFINER IS
   co_true  CONSTANT INTEGER := 1;
   co_false CONSTANT INTEGER := 0;
   FUNCTION true# RETURN INTEGER DETERMINISTIC;
   FUNCTION false# RETURN INTEGER DETERMINISTIC;
END const_boolean;
/
CREATE OR REPLACE PACKAGE BODY const_boolean IS
   FUNCTION true# RETURN INTEGER DETERMINISTIC IS
   BEGIN
      RETURN co_true;
   END true#;
   FUNCTION false# RETURN INTEGER DETERMINISTIC IS
   BEGIN
     RETURN co_false;
   END false#;
END const_boolean;
/" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">CREATE OR REPLACE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">PACKAGE</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">const_boolean</span><span style="color: #D4D4D4"> AUTHID DEFINER </span><span style="color: #569CD6">IS</span></span>
<span class="line"><span style="color: #D4D4D4">   co_true  </span><span style="color: #569CD6">CONSTANT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">INTEGER</span><span style="color: #D4D4D4"> := </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">   co_false </span><span style="color: #569CD6">CONSTANT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">INTEGER</span><span style="color: #D4D4D4"> := </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">FUNCTION</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">true</span><span style="color: #D4D4D4"># </span><span style="color: #C586C0">RETURN</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">INTEGER</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">DETERMINISTIC</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">FUNCTION</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">false</span><span style="color: #D4D4D4"># </span><span style="color: #C586C0">RETURN</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">INTEGER</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">DETERMINISTIC</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> const_boolean;</span></span>
<span class="line"><span style="color: #D4D4D4">/</span></span>
<span class="line"><span style="color: #569CD6">CREATE OR REPLACE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">PACKAGE BODY</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">const_boolean</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">IS</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">FUNCTION</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">true</span><span style="color: #D4D4D4"># </span><span style="color: #C586C0">RETURN</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">INTEGER</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">DETERMINISTIC</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">IS</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">BEGIN</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #C586C0">RETURN</span><span style="color: #D4D4D4"> co_true;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">true</span><span style="color: #D4D4D4">#;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">FUNCTION</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">false</span><span style="color: #D4D4D4"># </span><span style="color: #C586C0">RETURN</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">INTEGER</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">DETERMINISTIC</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">IS</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">BEGIN</span></span>
<span class="line"><span style="color: #D4D4D4">     </span><span style="color: #C586C0">RETURN</span><span style="color: #D4D4D4"> co_false;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">false</span><span style="color: #D4D4D4">#;</span></span>
<span class="line"><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> const_boolean;</span></span>
<span class="line"><span style="color: #D4D4D4">/</span></span></code></pre></div>



<p>Now we can use the function in PL/SQL and SQL like this:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">SQL</span><span role="button" tabindex="0" data-code="SELECT count(*) AS open_count
  FROM t 
 WHERE ind = const_boolean.true#;

OPEN_COUNT
----------
       101" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">count</span><span style="color: #D4D4D4">(*) </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> open_count</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> t </span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> ind = const_boolean.true#;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">OPEN_COUNT</span></span>
<span class="line"><span style="color: #6A9955">----------</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #B5CEA8">101</span></span></code></pre></div>



<p>So far so good.</p>



<h2 class="wp-block-heading">4. The Problem</h2>



<p>The execution plan of the previous statement looks as follows:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Bad execution plan</span><span role="button" tabindex="0" data-code="SQL_ID  bg67gqa8f48j8, child number 0
-------------------------------------
SELECT count(*) AS open_count  FROM t  WHERE ind = const_boolean.true#
 
Plan hash value: 3395265327
 
-----------------------------------------------------------------------------------
| Id  | Operation             | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |           |       |       |    75 (100)|          |
|   1 |  SORT AGGREGATE       |           |     1 |     3 |            |          |
|*  2 |   INDEX FAST FULL SCAN| T_IND_IDX | 50000 |   146K|    75  (12)| 00:00:01 |
-----------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   2 - filter(&quot;IND&quot;=&quot;CONST_BOOLEAN&quot;.&quot;TRUE#&quot;())" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">SQL_ID  bg67gqa8f48j8, child number 0</span></span>
<span class="line"><span style="color: #D4D4D4">-------------------------------------</span></span>
<span class="line"><span style="color: #D4D4D4">SELECT count(*) AS open_count  FROM t  WHERE ind = const_boolean.true#</span></span>
<span class="line"><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">Plan hash value: 3395265327</span></span>
<span class="line"><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">-----------------------------------------------------------------------------------</span></span>
<span class="line"><span style="color: #D4D4D4">| Id  | Operation             | Name      | Rows  | Bytes | Cost (%CPU)| Time     |</span></span>
<span class="line"><span style="color: #D4D4D4">-----------------------------------------------------------------------------------</span></span>
<span class="line"><span style="color: #D4D4D4">|   0 | SELECT STATEMENT      |           |       |       |    75 (100)|          |</span></span>
<span class="line"><span style="color: #D4D4D4">|   1 |  SORT AGGREGATE       |           |     1 |     3 |            |          |</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">|*  2 |   INDEX FAST FULL SCAN| T_IND_IDX | 50000 |   146K|    75  (12)| 00:00:01 |</span></span>
<span class="line"><span style="color: #D4D4D4">-----------------------------------------------------------------------------------</span></span>
<span class="line"><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">Predicate Information (identified by operation id):</span></span>
<span class="line"><span style="color: #D4D4D4">---------------------------------------------------</span></span>
<span class="line"><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">   2 - filter(&quot;IND&quot;=&quot;CONST_BOOLEAN&quot;.&quot;TRUE#&quot;())</span></span></code></pre></div>



<p>When you look at line 12 you see that the optimizer estimates to process 50000 rows. That&#8217;s 50 percent of all rows. This is based on the number of distinct values for column <code>ind</code> and the number of rows in the table <code>t</code>. The optimizer gets this information from here:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Table and column statistics</span><span role="button" tabindex="0" data-code="SELECT num_rows 
  FROM user_tables 
 WHERE table_name = 'T';

  NUM_ROWS
----------
    100000

SELECT num_distinct 
  FROM user_tab_columns
 WHERE table_name = 'T'
   AND column_name = 'IND';

NUM_DISTINCT
------------
           2" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> num_rows </span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> user_tables </span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> table_name = </span><span style="color: #CE9178">&#39;T&#39;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">  NUM_ROWS</span></span>
<span class="line"><span style="color: #6A9955">----------</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #B5CEA8">100000</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> num_distinct </span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> user_tab_columns</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> table_name = </span><span style="color: #CE9178">&#39;T&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> column_name = </span><span style="color: #CE9178">&#39;IND&#39;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">NUM_DISTINCT</span></span>
<span class="line"><span style="color: #6A9955">------------</span></span>
<span class="line"><span style="color: #D4D4D4">           </span><span style="color: #B5CEA8">2</span></span></code></pre></div>



<p>Unfortunately, the histogram for the column <code>ind</code> is ignored. Why? Because the Oracle Database has no idea what the value of <code>const_boolean.true#</code>  is. Hence, a histogram is not helpful in finding an execution plan.</p>



<p>An optimal plan would look like this:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Good execution plan</span><span role="button" tabindex="0" data-code="SQL_ID  bstdc2tsv1qcw, child number 0
-------------------------------------
SELECT count(*) AS open_count  FROM t  WHERE ind = 1
 
Plan hash value: 3365671116
 
-------------------------------------------------------------------------------
| Id  | Operation         | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |           |       |       |     1 (100)|          |
|   1 |  SORT AGGREGATE   |           |     1 |     3 |            |          |
|*  2 |   INDEX RANGE SCAN| T_IND_IDX |   101 |   303 |     1   (0)| 00:00:01 |
-------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   2 - access(&quot;IND&quot;=1)" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">SQL_ID  bstdc2tsv1qcw, child number 0</span></span>
<span class="line"><span style="color: #D4D4D4">-------------------------------------</span></span>
<span class="line"><span style="color: #D4D4D4">SELECT count(*) AS open_count  FROM t  WHERE ind = 1</span></span>
<span class="line"><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">Plan hash value: 3365671116</span></span>
<span class="line"><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">-------------------------------------------------------------------------------</span></span>
<span class="line"><span style="color: #D4D4D4">| Id  | Operation         | Name      | Rows  | Bytes | Cost (%CPU)| Time     |</span></span>
<span class="line"><span style="color: #D4D4D4">-------------------------------------------------------------------------------</span></span>
<span class="line"><span style="color: #D4D4D4">|   0 | SELECT STATEMENT  |           |       |       |     1 (100)|          |</span></span>
<span class="line"><span style="color: #D4D4D4">|   1 |  SORT AGGREGATE   |           |     1 |     3 |            |          |</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">|*  2 |   INDEX RANGE SCAN| T_IND_IDX |   101 |   303 |     1   (0)| 00:00:01 |</span></span>
<span class="line"><span style="color: #D4D4D4">-------------------------------------------------------------------------------</span></span>
<span class="line"><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">Predicate Information (identified by operation id):</span></span>
<span class="line"><span style="color: #D4D4D4">---------------------------------------------------</span></span>
<span class="line"><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">   2 - access(&quot;IND&quot;=1)</span></span></code></pre></div>



<p>When you look at line 12, you see that</p>



<ol class="wp-block-list">
<li>an <code>INDEX RANGE SCAN</code> is used and</li>



<li>the number of rows is estimated correctly.</li>
</ol>



<p>We get this plan when using a literal <code>1</code>, a bind variable with the bind value <code>1</code> (thanks to bind variable peeking) or a constant with value <code>1</code> (which is treated as a bind variable in PL/SQL).</p>



<p>The wrong cardinality is a major problem. Because the cardinality is the most important criterion for choosing an optimal access method, join order and join method. Bad cardinality estimates lead to bad execution plans and bad performance. This cannot be ignored, even if in this demo case the resulting performance is still okay.</p>



<p>The problem occurs only if we are accessing columns with significantly skewed data and if these columns have a histogram.</p>



<h2 class="wp-block-heading">5. Workarounds</h2>



<p>We have basically three options to work around the problem:</p>



<ol class="wp-block-list">
<li>For PL/SQL code we can use a constant instead of a parameterless function<br />(e.g. <code>ind = const_boolean.co_true</code>)</li>



<li>For PL/SQL code or plain SQL like in views, we can use a literal with a comment instead of a parameterless function<br />(e.g. <code>ind = 1 -- const_boolean.co_true</code>)</li>



<li><em>For PL/SQL code or plain SQL like in views, we can query the parameterless function in a subquery and force the optimizer to execute it during parse time [added on 2019-12-14]</em><br /><em>(e.g. <code>ind IN (SELECT /*+ precompute_subquery */ const_boolean.true# FROM DUAL)</code>)</em></li>
</ol>



<p>The first option has the drawback, that you have to change the SQL to make it runnable outside of PL/SQL. The second option may lead to inconsistencies due to wrong literal/comment combinations or when changing constant values. <em>The third option requires an <a href="https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/IN-Condition.html#GUID-C7961CB3-8F60-47E0-96EB-BDCF5DB1317C">IN condition</a> that could be accidentally changed to an <a href="https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/Comparison-Conditions.html#GUID-2590303E-81FE-4758-A971-1EE8B798951F">equal comparison condition</a> due to the <a href="https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/Scalar-Subquery-Expressions.html#GUID-475D80C3-C873-4475-AB1A-8837C5CF8CE4">scalar subquery</a>, which would make the undocumented <a href="https://blog.tanelpoder.com/2009/01/23/multipart-cursor-subexecution-and-precompute_subquery-hint/">precompute_subquery hint</a> ineffective. [added on 2019-12-14]</em></p>



<p>Of course, you can continue to use parameterless functions in SQL and PL/SQL and switch to one of the options if there is a problem or if you know that a histogram exists for a certain column. But this is difficult to apply consistently. In fact, it makes maintenance more complicated with a certain performance risk or penalty.</p>



<h2 class="wp-block-heading">6. Considered Alternatives</h2>



<p>I had a look at <a href="https://docs.oracle.com/en/database/oracle/oracle-database/19/addci/using-extensible-optimizer.html#GUID-90DC8855-4A40-480F-B574-4D82A227B4F4">Associate Statistics (Extensible Optimizer Interface)</a>. This does not help, because there is no way to access the related table columns to calculate the impact on the selectivity. The feature is useful if a function gets some parameters to calculate the impact on the selectivity, but without parameters, this is not possible.</p>



<p>I had considered <a href="https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/CREATE-TABLE.html#GUID-F9CE0CC3-13AE-4744-A43C-EAC7A71AAAB6__I2146309">list partitioned</a> tables based on skewed columns instead of using indexes. This works and can make sense to reduce the overhead of an index (especially indexing non-selective values). But the issues regarding parameterless functions are 100 percent the same.</p>



<h2 class="wp-block-heading">7. Summary</h2>



<p>Parameterless functions are a way to use constants in SQL outside of PL/SQL, for example in views. However, they rob the optimizer of the capability to use histograms and therefore find an optimal execution plan.</p>



<p>Actually, we can only work around the problem. The Oracle Database has to provide the solution. Either by allowing to access package global constants in SQL (outside of PL/SQL) or by implementing some kind of peeking for parameterless, deterministic functions.</p>



<p>If you think I missed something important, especially if you think there is a better workaround or even a solution, then please do not hesitate to leave a comment or contact me directly. Thank you.</p>



<p><em>Updated on 2019-12-14, added a third option under &#8220;5. Workarounds&#8221; based on a <a href="https://twitter.com/JLOracle/status/1205804594238050304">tweet</a> by <a href="https://twitter.com/JLOracle">Jonathan Lewis</a>. Thanks a lot.</em></p>
<p>The post <a href="https://www.salvis.com/blog/2019/12/13/constants-vs-parameterless-functions/">Constants vs. Parameterless Functions</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.salvis.com/blog/2019/12/13/constants-vs-parameterless-functions/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title>MemOptimized RowStore in Oracle Database 19c</title>
		<link>https://www.salvis.com/blog/2019/02/17/memoptimized-rowstore-in-oracle-database-19c/</link>
					<comments>https://www.salvis.com/blog/2019/02/17/memoptimized-rowstore-in-oracle-database-19c/#comments</comments>
		
		<dc:creator><![CDATA[Philipp Salvisberg]]></dc:creator>
		<pubDate>Sun, 17 Feb 2019 20:15:42 +0000</pubDate>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[PL/SQL]]></category>
		<category><![CDATA[SQL]]></category>
		<guid isPermaLink="false">https://www.salvis.com/blog/?p=9100</guid>

					<description><![CDATA[<p>Since February 13 2019 Oracle Database 19c has been available. I blogged about this feature here and here. Time for an update. So, what&#8217;s new in 19c regarding the MemOptimized Rowstore? Fast Lookup Works with JDBC Thin Driver I listed 16 prerequisites for the MemOptimized Rowstore in this blog post. The last one &#8211;<span class="excerpt-hellip"> […]</span></p>
<p>The post <a href="https://www.salvis.com/blog/2019/02/17/memoptimized-rowstore-in-oracle-database-19c/">MemOptimized RowStore in Oracle Database 19c</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Since February 13 2019 Oracle Database 19c has been available. I blogged about this feature <a href="https://www.salvis.com/blog/2018/06/10/memoptimized-rowstore-in-oracle-database-18c/">here</a> and <a href="https://www.salvis.com/blog/2018/06/19/memoptimized-rowstore-in-oracle-database-18c-with-oci/">here</a>. Time for an update. So, what&#8217;s new in 19c regarding the MemOptimized Rowstore?</p>



<h2 class="wp-block-heading">Fast Lookup Works with JDBC Thin Driver</h2>



<p>I listed 16 prerequisites for the MemOptimized Rowstore in <a href="https://www.salvis.com/blog/2018/06/10/memoptimized-rowstore-in-oracle-database-18c/">this blog post</a>. The last one &#8211; &#8220;The query must not be executed from a JDBC thin driver connection. You have to use OCI, otherwise the performance will be really bad.&#8221; does not apply anymore. This &#8220;bug&#8221; is fixed in 19c. Here are the JDBC thin driver results of the test program listed in <a href="https://www.salvis.com/blog/2018/06/19/memoptimized-rowstore-in-oracle-database-18c-with-oci/">this blog post:</a></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Console output of run.sh (excerpt) with comments</span><span role="button" tabindex="0" data-code="# t1 - heap table
run #1: read 100000 rows from t1 in 18.602 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.
run #2: read 100000 rows from t1 in 17.723 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.
run #3: read 100000 rows from t1 in 18.834 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.
run #4: read 100000 rows from t1 in 18.039 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.
run #5: read 100000 rows from t1 in 18.711 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.

# t4 - memoptimized heap-table
run #1: read 100000 rows from t4 in 16.696 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.
run #2: read 100000 rows from t4 in 16.671 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.
run #3: read 100000 rows from t4 in 16.952 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.
run #4: read 100000 rows from t4 in 16.805 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.
run #5: read 100000 rows from t4 in 17.627 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker." style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4"># t1 - heap </span><span style="color: #569CD6">table</span></span>
<span class="line"><span style="color: #D4D4D4">run #</span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">: </span><span style="color: #569CD6">read</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">100000</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">rows</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> t1 </span><span style="color: #569CD6">in</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">18</span><span style="color: #D4D4D4">.</span><span style="color: #B5CEA8">602</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">seconds</span><span style="color: #D4D4D4"> via jdbc:oracle:thin:@//localhost:</span><span style="color: #B5CEA8">1521</span><span style="color: #D4D4D4">/odb.docker.</span></span>
<span class="line"><span style="color: #D4D4D4">run #</span><span style="color: #B5CEA8">2</span><span style="color: #D4D4D4">: </span><span style="color: #569CD6">read</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">100000</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">rows</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> t1 </span><span style="color: #569CD6">in</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">17</span><span style="color: #D4D4D4">.</span><span style="color: #B5CEA8">723</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">seconds</span><span style="color: #D4D4D4"> via jdbc:oracle:thin:@//localhost:</span><span style="color: #B5CEA8">1521</span><span style="color: #D4D4D4">/odb.docker.</span></span>
<span class="line"><span style="color: #D4D4D4">run #</span><span style="color: #B5CEA8">3</span><span style="color: #D4D4D4">: </span><span style="color: #569CD6">read</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">100000</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">rows</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> t1 </span><span style="color: #569CD6">in</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">18</span><span style="color: #D4D4D4">.</span><span style="color: #B5CEA8">834</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">seconds</span><span style="color: #D4D4D4"> via jdbc:oracle:thin:@//localhost:</span><span style="color: #B5CEA8">1521</span><span style="color: #D4D4D4">/odb.docker.</span></span>
<span class="line"><span style="color: #D4D4D4">run #</span><span style="color: #B5CEA8">4</span><span style="color: #D4D4D4">: </span><span style="color: #569CD6">read</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">100000</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">rows</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> t1 </span><span style="color: #569CD6">in</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">18</span><span style="color: #D4D4D4">.</span><span style="color: #B5CEA8">039</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">seconds</span><span style="color: #D4D4D4"> via jdbc:oracle:thin:@//localhost:</span><span style="color: #B5CEA8">1521</span><span style="color: #D4D4D4">/odb.docker.</span></span>
<span class="line"><span style="color: #D4D4D4">run #</span><span style="color: #B5CEA8">5</span><span style="color: #D4D4D4">: </span><span style="color: #569CD6">read</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">100000</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">rows</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> t1 </span><span style="color: #569CD6">in</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">18</span><span style="color: #D4D4D4">.</span><span style="color: #B5CEA8">711</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">seconds</span><span style="color: #D4D4D4"> via jdbc:oracle:thin:@//localhost:</span><span style="color: #B5CEA8">1521</span><span style="color: #D4D4D4">/odb.docker.</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4"># t4 - memoptimized heap-</span><span style="color: #569CD6">table</span></span>
<span class="line"><span style="color: #D4D4D4">run #</span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">: </span><span style="color: #569CD6">read</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">100000</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">rows</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> t4 </span><span style="color: #569CD6">in</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">16</span><span style="color: #D4D4D4">.</span><span style="color: #B5CEA8">696</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">seconds</span><span style="color: #D4D4D4"> via jdbc:oracle:thin:@//localhost:</span><span style="color: #B5CEA8">1521</span><span style="color: #D4D4D4">/odb.docker.</span></span>
<span class="line"><span style="color: #D4D4D4">run #</span><span style="color: #B5CEA8">2</span><span style="color: #D4D4D4">: </span><span style="color: #569CD6">read</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">100000</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">rows</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> t4 </span><span style="color: #569CD6">in</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">16</span><span style="color: #D4D4D4">.</span><span style="color: #B5CEA8">671</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">seconds</span><span style="color: #D4D4D4"> via jdbc:oracle:thin:@//localhost:</span><span style="color: #B5CEA8">1521</span><span style="color: #D4D4D4">/odb.docker.</span></span>
<span class="line"><span style="color: #D4D4D4">run #</span><span style="color: #B5CEA8">3</span><span style="color: #D4D4D4">: </span><span style="color: #569CD6">read</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">100000</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">rows</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> t4 </span><span style="color: #569CD6">in</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">16</span><span style="color: #D4D4D4">.</span><span style="color: #B5CEA8">952</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">seconds</span><span style="color: #D4D4D4"> via jdbc:oracle:thin:@//localhost:</span><span style="color: #B5CEA8">1521</span><span style="color: #D4D4D4">/odb.docker.</span></span>
<span class="line"><span style="color: #D4D4D4">run #</span><span style="color: #B5CEA8">4</span><span style="color: #D4D4D4">: </span><span style="color: #569CD6">read</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">100000</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">rows</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> t4 </span><span style="color: #569CD6">in</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">16</span><span style="color: #D4D4D4">.</span><span style="color: #B5CEA8">805</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">seconds</span><span style="color: #D4D4D4"> via jdbc:oracle:thin:@//localhost:</span><span style="color: #B5CEA8">1521</span><span style="color: #D4D4D4">/odb.docker.</span></span>
<span class="line"><span style="color: #D4D4D4">run #</span><span style="color: #B5CEA8">5</span><span style="color: #D4D4D4">: </span><span style="color: #569CD6">read</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">100000</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">rows</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> t4 </span><span style="color: #569CD6">in</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">17</span><span style="color: #D4D4D4">.</span><span style="color: #B5CEA8">627</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">seconds</span><span style="color: #D4D4D4"> via jdbc:oracle:thin:@//localhost:</span><span style="color: #B5CEA8">1521</span><span style="color: #D4D4D4">/odb.docker.</span></span></code></pre></div>



<p>See, the runs for <code>t4</code> are the fastest because they used <code>memopt r lookups</code>  instead of  <code>consistent gets</code>.  BTW, the absolute runtime values of these tests are not important or representative, they vary a lot depending on the Docker environment that I use. However, I consider the relative difference between the <code>t1</code> and <code>t4</code> as relevant and conclusive. The next graph visualizes the results. I also added the results for the PL/SQL runs to this graph. It clearly shows that if you can do it within the database, you should do it.</p>



<figure class="wp-block-image"><a href="https://www.salvis.com/blog/wp-content/uploads/2019/02/memoptimized_rowstore_19c_thin_driver-1.png"><img decoding="async" width="945" height="533" src="https://www.salvis.com/blog/wp-content/uploads/2019/02/memoptimized_rowstore_19c_thin_driver-1.png" alt="" class="wp-image-9109" srcset="https://www.salvis.com/blog/wp-content/uploads/2019/02/memoptimized_rowstore_19c_thin_driver-1.png 945w, https://www.salvis.com/blog/wp-content/uploads/2019/02/memoptimized_rowstore_19c_thin_driver-1-300x169.png 300w, https://www.salvis.com/blog/wp-content/uploads/2019/02/memoptimized_rowstore_19c_thin_driver-1-768x433.png 768w, https://www.salvis.com/blog/wp-content/uploads/2019/02/memoptimized_rowstore_19c_thin_driver-1-260x146.png 260w, https://www.salvis.com/blog/wp-content/uploads/2019/02/memoptimized_rowstore_19c_thin_driver-1-50x28.png 50w, https://www.salvis.com/blog/wp-content/uploads/2019/02/memoptimized_rowstore_19c_thin_driver-1-133x75.png 133w" sizes="(max-width:767px) 480px, (max-width:945px) 100vw, 945px" /></a></figure>



<p>I also run this test for 18.5.0.0.0. It looks like this bug has not been fixed in 18c yet.</p>



<h2 class="wp-block-heading">Fast Ingest</h2>



<p>This new 19c feature consists of two parts. The usage is best described in the <a href="https://docs.oracle.com/en/database/oracle/oracle-database/19/tgdba/tuning-system-global-area.html#GUID-CFADC9EA-2E2F-4EBB-BA2C-3663291DCC25">Database Performance Tuning Guide</a>.</p>



<p>First, the table must be enabled for memoptimized write using the memoptimize_write_clause. You can do that in the <code>create table</code>&nbsp;or the <code>alter table</code>&nbsp;statement. Here&#8217;s an example:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Example of memoptimize_write_clause</span><span role="button" tabindex="0" data-code="CREATE TABLE t5 (
   key    INTEGER            NOT NULL,
   value  VARCHAR2(30 CHAR)  NOT NULL,
   CONSTRAINT t5_pk PRIMARY KEY (key)
) 
SEGMENT CREATION IMMEDIATE
MEMOPTIMIZE FOR WRITE;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">CREATE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">TABLE</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">t5</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">key</span><span style="color: #D4D4D4">    </span><span style="color: #569CD6">INTEGER</span><span style="color: #D4D4D4">            </span><span style="color: #569CD6">NOT NULL</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">value</span><span style="color: #D4D4D4">  </span><span style="color: #569CD6">VARCHAR2</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">30</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">CHAR</span><span style="color: #D4D4D4">)  </span><span style="color: #569CD6">NOT NULL</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">CONSTRAINT</span><span style="color: #D4D4D4"> t5_pk </span><span style="color: #569CD6">PRIMARY KEY</span><span style="color: #D4D4D4"> (</span><span style="color: #569CD6">key</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">) </span></span>
<span class="line"><span style="color: #D4D4D4">SEGMENT CREATION </span><span style="color: #569CD6">IMMEDIATE</span></span>
<span class="line"><span style="color: #D4D4D4">MEMOPTIMIZE </span><span style="color: #569CD6">FOR</span><span style="color: #D4D4D4"> WRITE;</span></span></code></pre></div>



<p>One way to trigger fast ingest is to use an insert hint. Here&#8217;s an example:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Fast ingest (autocommit)</span><span role="button" tabindex="0" data-code="BEGIN
   FOR r IN (SELECT * FROM t4 WHERE key between 10001 and 20000) LOOP
      INSERT /*+ memoptimize_write */ INTO t5 VALUES r;
   END LOOP;
END;
/" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">BEGIN</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">FOR</span><span style="color: #D4D4D4"> r </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> * </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> t4 </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">key</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">between</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">10001</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">and</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">20000</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">LOOP</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">INSERT</span><span style="color: #D4D4D4"> </span><span style="color: #6A9955">/*+ memoptimize_write */</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">INTO</span><span style="color: #D4D4D4"> t5 </span><span style="color: #569CD6">VALUES</span><span style="color: #D4D4D4"> r;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">LOOP</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #569CD6">END</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">/</span></span></code></pre></div>



<p>There is no <code>commit</code>&nbsp;in this anonymous PL/SQL block. In this case an additional <code>commit</code>&nbsp;statement would just slow down the processing. The insert statements are treated like asynchronous transactions. This mechanism is called „delayed inserts“. The rows to be inserted are collected in the large pool and processed asynchronously in batches using direct path inserts. That will happen eventually. However, you can call <code>dbms_memoptimize_admin.writes_flush</code>&nbsp;to force the rows in the large pool to be written to disk.</p>



<p>Fast ingest is much more efficient than a series of conventional single transactions. But, there are some disadvantages to consider.</p>



<ol class="wp-block-list">
<li>Data loss in case of a crash of the database instance</li>



<li>Delayed visibility of inserted data</li>



<li>Delayed visibility of errors</li>
</ol>



<p>The first two are simply the price to optimize the insert performance of multiple clients. However, the last one is interesting. Where are errors reported in this case and how do we deal with them?</p>



<p>Here&#8217;s an example.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Fast ingest with a duplicate row</span><span role="button" tabindex="0" data-code="SELECT * FROM t5 WHERE key IN (10001, 20001);

       KEY VALUE                         
---------- ------------------------------
     10001 PAST7NL2N2W8K9ESS7BZWSI   

BEGIN
   FOR r IN (SELECT * FROM t4 WHERE key IN (10001, 20001)) LOOP
      INSERT /*+ memoptimize_write */ INTO t5 VALUES r;
   END LOOP;
   dbms_memoptimize_admin.writes_flush;
END;
/

PL/SQL procedure successfully completed.

SELECT * FROM t5 WHERE key IN (10001, 20001);

       KEY VALUE                         
---------- ------------------------------
     10001 PAST7NL2N2W8K9ESS7BZWSI       
     20001 4IMKI9RLBTV7                  
" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> * </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> t5 </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> key </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span><span style="color: #B5CEA8">10001</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">20001</span><span style="color: #D4D4D4">);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">       KEY VALUE                         </span></span>
<span class="line"><span style="color: #6A9955">---------- ------------------------------</span></span>
<span class="line"><span style="color: #D4D4D4">     </span><span style="color: #B5CEA8">10001</span><span style="color: #D4D4D4"> PAST7NL2N2W8K9ESS7BZWSI   </span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">BEGIN</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #C586C0">FOR</span><span style="color: #D4D4D4"> r </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> * </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> t4 </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> key </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span><span style="color: #B5CEA8">10001</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">20001</span><span style="color: #D4D4D4">)) </span><span style="color: #C586C0">LOOP</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">INSERT</span><span style="color: #D4D4D4"> </span><span style="color: #6A9955">/*+ memoptimize_write */</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">INTO</span><span style="color: #D4D4D4"> t5 </span><span style="color: #569CD6">VALUES</span><span style="color: #D4D4D4"> r;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #C586C0">END LOOP</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #DCDCAA">dbms_memoptimize_admin.</span><span style="color: #4EC9B0">writes_flush</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #569CD6">END</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">/</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">PL/</span><span style="color: #569CD6">SQL</span><span style="color: #D4D4D4"> procedure successfully completed.</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> * </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> t5 </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> key </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span><span style="color: #B5CEA8">10001</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">20001</span><span style="color: #D4D4D4">);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">       KEY VALUE                         </span></span>
<span class="line"><span style="color: #6A9955">---------- ------------------------------</span></span>
<span class="line"><span style="color: #D4D4D4">     </span><span style="color: #B5CEA8">10001</span><span style="color: #D4D4D4"> PAST7NL2N2W8K9ESS7BZWSI       </span></span>
<span class="line"><span style="color: #D4D4D4">     </span><span style="color: #B5CEA8">20001</span><span style="color: #D4D4D4"> 4IMKI9RLBTV7                  </span></span>
<span class="line"></span></code></pre></div>



<p>Fast ingest persisted the non-existing row with the key <code>20001</code>. But the row with the existing key <code>10001</code> was ignored. Somewhere an <code>ORA-00001: unique constraint violated</code> must have been thrown. But right now I do not know If it was just swallowed or stored somewhere (I have not found the trace file mentioned in <a href="https://docs.oracle.com/en/database/oracle/oracle-database/19/cncpt/memory-architecture.html#GUID-07D4439A-8E4E-4FBC-A403-1B0F0B9E0058">Database Concepts</a>). If ignoring is the right way to deal with such errors, then we are all set. Otherwise, we have to think a bit more about it.</p>
<p>The post <a href="https://www.salvis.com/blog/2019/02/17/memoptimized-rowstore-in-oracle-database-19c/">MemOptimized RowStore in Oracle Database 19c</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.salvis.com/blog/2019/02/17/memoptimized-rowstore-in-oracle-database-19c/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>MemOptimized RowStore in Oracle Database 18c with OCI</title>
		<link>https://www.salvis.com/blog/2018/06/19/memoptimized-rowstore-in-oracle-database-18c-with-oci/</link>
					<comments>https://www.salvis.com/blog/2018/06/19/memoptimized-rowstore-in-oracle-database-18c-with-oci/#comments</comments>
		
		<dc:creator><![CDATA[Philipp Salvisberg]]></dc:creator>
		<pubDate>Tue, 19 Jun 2018 19:34:51 +0000</pubDate>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[PL/SQL]]></category>
		<category><![CDATA[SQL]]></category>
		<guid isPermaLink="false">https://www.salvis.com/blog/?p=8492</guid>

					<description><![CDATA[<p>On June 10 2018 I blogged about the MemOptimized RowStore in Oracle Database 18c. If you haven&#8217;t read this post, it is a good idea to catch up now. I showed that accessing a memoptimized table t4 via the MemOptimized RowStore was around 60% slower than accessing a heap-organized table t1. I<span class="excerpt-hellip"> […]</span></p>
<p>The post <a href="https://www.salvis.com/blog/2018/06/19/memoptimized-rowstore-in-oracle-database-18c-with-oci/">MemOptimized RowStore in Oracle Database 18c with OCI</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>On June 10 2018 I blogged about the <a href="https://www.salvis.com/blog/2018/06/10/memoptimized-rowstore-in-oracle-database-18c/">MemOptimized RowStore in Oracle Database 18c</a>. If you haven&#8217;t read this post, it is a good idea to catch up now. I showed that accessing a memoptimized table <code>t4</code> via the MemOptimized RowStore was around 60% slower than accessing a heap-organized table <code>t1</code>. I suspected that this disappointing result was related to my unsupported Docker environment. But I was wrong.</p>



<p>The next day, Chris Antognini contacted me, since he planned to talk about this feature at the <a href="http://www.aoug.at/Event/474">AOUG Anwenderkonferenz 2018</a>.&nbsp;We exchanged our thoughts and shared our findings. Chris did his tests in the Oracle cloud and could also reproduce my test results.&nbsp;That&#8217;s interesting. Even more interesting is, that Chris translated my Java program to C and proved that the MemOptimized RowStore can be fast.&nbsp;That&#8217;s cool. But why didn&#8217;t it work in Java? It&#8217;s the same after all, right? No. The Java program used the JDBC thin driver and the C program OCI.</p>



<p>In this blog post, I will show that OCI is a prerequisite for getting good performance out of the MemOptimized RowStore.</p>



<h2 class="wp-block-heading">The Program</h2>



<p>I use the Java program from my previous post. I only added 3 parameters. The JDBC URL, the username and the password. Here&#8217;s the program.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">J.java &#8211; 100,000 queries</span><span role="button" tabindex="0" data-code="import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import oracle.jdbc.driver.OracleDriver;
public class J {
   private static boolean isRunningInDatabase() {
      return System.getProperty(&quot;oracle.jserver.version&quot;) != null;
   }
   public static void m(String tableName, String url, String userName, String password) throws SQLException {
      Connection conn;
      if (isRunningInDatabase()) {
         conn = new OracleDriver().defaultConnection();
      } else {
         conn = DriverManager.getConnection(
           url, userName, password);
      }
      conn.setAutoCommit(false);
      long start = System.currentTimeMillis();
      String query = &quot;SELECT value FROM &quot; + tableName + &quot; WHERE key = ?&quot;;      
      PreparedStatement ps = conn.prepareStatement(query);
      for (long i = 1; i <= 100000; i++) {
         ps.setLong(1, i);
         ResultSet rs = ps.executeQuery();
         while (rs.next()) {
            rs.getString(&quot;value&quot;);
         }
         rs.close();
      }
      ps.close();
      if (!isRunningInDatabase()) {
         conn.close();
      }
      long end = System.currentTimeMillis();
      System.out.println(&quot;read 100000 rows from &quot; + tableName + &quot; in &quot; +
         String.valueOf((double) (end-start)/1000) + &quot; seconds via &quot; + url + &quot;.&quot;);      
   }
   public static void main(String[] args) throws SQLException {
      m(args[0], args[1], args[2], args[3]);
   }
}" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">import</span><span style="color: #D4D4D4"> java.sql.Connection;</span></span>
<span class="line"><span style="color: #569CD6">import</span><span style="color: #D4D4D4"> java.sql.DriverManager;</span></span>
<span class="line"><span style="color: #569CD6">import</span><span style="color: #D4D4D4"> java.sql.PreparedStatement;</span></span>
<span class="line"><span style="color: #569CD6">import</span><span style="color: #D4D4D4"> java.sql.ResultSet;</span></span>
<span class="line"><span style="color: #569CD6">import</span><span style="color: #D4D4D4"> java.sql.SQLException;</span></span>
<span class="line"><span style="color: #569CD6">import</span><span style="color: #D4D4D4"> oracle.jdbc.driver.OracleDriver;</span></span>
<span class="line"><span style="color: #569CD6">public</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">class</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">J</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">private</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">static</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">boolean</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">isRunningInDatabase</span><span style="color: #D4D4D4">() {</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">System</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">getProperty</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;oracle.jserver.version&quot;</span><span style="color: #D4D4D4">) != </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">   }</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">public</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">static</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">void</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">m</span><span style="color: #D4D4D4">(</span><span style="color: #4EC9B0">String</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">tableName</span><span style="color: #D4D4D4">, </span><span style="color: #4EC9B0">String</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">url</span><span style="color: #D4D4D4">, </span><span style="color: #4EC9B0">String</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">userName</span><span style="color: #D4D4D4">, </span><span style="color: #4EC9B0">String</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">password</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">throws</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">SQLException</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #4EC9B0">Connection</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">conn</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> (</span><span style="color: #DCDCAA">isRunningInDatabase</span><span style="color: #D4D4D4">()) {</span></span>
<span class="line"><span style="color: #D4D4D4">         conn = </span><span style="color: #C586C0">new</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">OracleDriver</span><span style="color: #D4D4D4">().</span><span style="color: #DCDCAA">defaultConnection</span><span style="color: #D4D4D4">();</span></span>
<span class="line"><span style="color: #D4D4D4">      } </span><span style="color: #C586C0">else</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">         conn = </span><span style="color: #9CDCFE">DriverManager</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">getConnection</span><span style="color: #D4D4D4">(</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">           url, userName, password);</span></span>
<span class="line"><span style="color: #D4D4D4">      }</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">conn</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">setAutoCommit</span><span style="color: #D4D4D4">(</span><span style="color: #569CD6">false</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #4EC9B0">long</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">start</span><span style="color: #D4D4D4"> = </span><span style="color: #9CDCFE">System</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">currentTimeMillis</span><span style="color: #D4D4D4">();</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">      </span><span style="color: #4EC9B0">String</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">query</span><span style="color: #D4D4D4"> = </span><span style="color: #CE9178">&quot;SELECT value FROM &quot;</span><span style="color: #D4D4D4"> + tableName + </span><span style="color: #CE9178">&quot; WHERE key = ?&quot;</span><span style="color: #D4D4D4">;      </span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #4EC9B0">PreparedStatement</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">ps</span><span style="color: #D4D4D4"> = </span><span style="color: #9CDCFE">conn</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">prepareStatement</span><span style="color: #D4D4D4">(query);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #C586C0">for</span><span style="color: #D4D4D4"> (</span><span style="color: #4EC9B0">long</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">i</span><span style="color: #D4D4D4"> = </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">; i &lt;= </span><span style="color: #B5CEA8">100000</span><span style="color: #D4D4D4">; i++) {</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #9CDCFE">ps</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">setLong</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">, i);</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #4EC9B0">ResultSet</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">rs</span><span style="color: #D4D4D4"> = </span><span style="color: #9CDCFE">ps</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">executeQuery</span><span style="color: #D4D4D4">();</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #C586C0">while</span><span style="color: #D4D4D4"> (</span><span style="color: #9CDCFE">rs</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">next</span><span style="color: #D4D4D4">()) {</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #9CDCFE">rs</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">getString</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;value&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">         }</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #9CDCFE">rs</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">close</span><span style="color: #D4D4D4">();</span></span>
<span class="line"><span style="color: #D4D4D4">      }</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">ps</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">close</span><span style="color: #D4D4D4">();</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> (!</span><span style="color: #DCDCAA">isRunningInDatabase</span><span style="color: #D4D4D4">()) {</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #9CDCFE">conn</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">close</span><span style="color: #D4D4D4">();</span></span>
<span class="line"><span style="color: #D4D4D4">      }</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #4EC9B0">long</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">end</span><span style="color: #D4D4D4"> = </span><span style="color: #9CDCFE">System</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">currentTimeMillis</span><span style="color: #D4D4D4">();</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">System</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">out</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">println</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;read 100000 rows from &quot;</span><span style="color: #D4D4D4"> + tableName + </span><span style="color: #CE9178">&quot; in &quot;</span><span style="color: #D4D4D4"> +</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #9CDCFE">String</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">valueOf</span><span style="color: #D4D4D4">((</span><span style="color: #4EC9B0">double</span><span style="color: #D4D4D4">) (end-start)/</span><span style="color: #B5CEA8">1000</span><span style="color: #D4D4D4">) + </span><span style="color: #CE9178">&quot; seconds via &quot;</span><span style="color: #D4D4D4"> + url + </span><span style="color: #CE9178">&quot;.&quot;</span><span style="color: #D4D4D4">);      </span></span>
<span class="line"><span style="color: #D4D4D4">   }</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">public</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">static</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">void</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">main</span><span style="color: #D4D4D4">(</span><span style="color: #4EC9B0">String</span><span style="color: #D4D4D4">[] </span><span style="color: #9CDCFE">args</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">throws</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">SQLException</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #DCDCAA">m</span><span style="color: #D4D4D4">(args[</span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">], args[</span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">], args[</span><span style="color: #B5CEA8">2</span><span style="color: #D4D4D4">], args[</span><span style="color: #B5CEA8">3</span><span style="color: #D4D4D4">]);</span></span>
<span class="line"><span style="color: #D4D4D4">   }</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<p>I copied this program to my Docker container into the directory <code>$ORACLE_HOME/jdbc/lib</code>&nbsp;and compiled it with the following script:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">compile.sh</span><span role="button" tabindex="0" data-code="export rt CLASSPATH=.:./ojdbc8.jar
javac J.java" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">export</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">rt</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">CLASSPATH=.:./ojdbc8.jar</span></span>
<span class="line"><span style="color: #DCDCAA">javac</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">J.java</span></span></code></pre></div>



<h2 class="wp-block-heading">The Test Script</h2>



<p>I&#8217;ve run the tests for my <a href="https://www.salvis.com/blog/2018/06/10/memoptimized-rowstore-in-oracle-database-18c/">previous post</a> from the Eclipse IDE because it was convenient for me to set a break point on line 20 to identify the Oracle process for <code>perf</code>. Now, I do not need to produce flame graphs. Running the test script on the server directly will also reduce the network overhead, especially when running without Oracle Net.</p>



<p>Here&#8217;s the test script:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">run.sh</span><span role="button" tabindex="0" data-code="#/bin/bash

run(){
    TABLE=${1}
    URL=${2}
    for ((i=1;i<=5;i++));
    do
        echo -n &quot;run #${i}: &quot;
        java J ${TABLE} ${URL} ${USERNAME} ${PASSWORD}
    done
    echo &quot;&quot;
} 

export CLASSPATH=.:./ojdbc8.jar
export USERNAME=tvdca
export PASSWORD=tvdca

# Thin driver
run t1 &quot;jdbc:oracle:thin:@//localhost:1521/odb.docker&quot;
run t2 &quot;jdbc:oracle:thin:@//localhost:1521/odb.docker&quot;
run t3 &quot;jdbc:oracle:thin:@//localhost:1521/odb.docker&quot;
run t4 &quot;jdbc:oracle:thin:@//localhost:1521/odb.docker&quot;

# OCI driver with Oracle*Net
run t1 &quot;jdbc:oracle:oci:@odb&quot;
run t2 &quot;jdbc:oracle:oci:@odb&quot;
run t3 &quot;jdbc:oracle:oci:@odb&quot;
run t4 &quot;jdbc:oracle:oci:@odb&quot;

# OCI driver without Oracle*Net
run t1 &quot;jdbc:oracle:oci:@&quot;
run t2 &quot;jdbc:oracle:oci:@&quot;
run t3 &quot;jdbc:oracle:oci:@&quot;
run t4 &quot;jdbc:oracle:oci:@&quot;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #6A9955">#/bin/bash</span></span>
<span class="line"></span>
<span class="line"><span style="color: #DCDCAA">run</span><span style="color: #D4D4D4">(){</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #9CDCFE">TABLE</span><span style="color: #D4D4D4">=</span><span style="color: #9CDCFE">${1}</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #9CDCFE">URL</span><span style="color: #D4D4D4">=</span><span style="color: #9CDCFE">${2}</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">for</span><span style="color: #D4D4D4"> ((i=</span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">;i&lt;=</span><span style="color: #B5CEA8">5</span><span style="color: #D4D4D4">;i++));</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">do</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #DCDCAA">echo</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-n</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;run #${</span><span style="color: #9CDCFE">i</span><span style="color: #CE9178">}: &quot;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #DCDCAA">java</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">J</span><span style="color: #D4D4D4"> ${</span><span style="color: #9CDCFE">TABLE</span><span style="color: #D4D4D4">} ${</span><span style="color: #9CDCFE">URL</span><span style="color: #D4D4D4">} ${</span><span style="color: #9CDCFE">USERNAME</span><span style="color: #D4D4D4">} ${</span><span style="color: #9CDCFE">PASSWORD</span><span style="color: #D4D4D4">}</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">done</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #DCDCAA">echo</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">} </span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">export</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">CLASSPATH</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">.:./ojdbc8.jar</span></span>
<span class="line"><span style="color: #569CD6">export</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">USERNAME</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">tvdca</span></span>
<span class="line"><span style="color: #569CD6">export</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">PASSWORD</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">tvdca</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955"># Thin driver</span></span>
<span class="line"><span style="color: #DCDCAA">run</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">t1</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;jdbc:oracle:thin:@//localhost:1521/odb.docker&quot;</span></span>
<span class="line"><span style="color: #DCDCAA">run</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">t2</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;jdbc:oracle:thin:@//localhost:1521/odb.docker&quot;</span></span>
<span class="line"><span style="color: #DCDCAA">run</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">t3</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;jdbc:oracle:thin:@//localhost:1521/odb.docker&quot;</span></span>
<span class="line"><span style="color: #DCDCAA">run</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">t4</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;jdbc:oracle:thin:@//localhost:1521/odb.docker&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955"># OCI driver with Oracle*Net</span></span>
<span class="line"><span style="color: #DCDCAA">run</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">t1</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;jdbc:oracle:oci:@odb&quot;</span></span>
<span class="line"><span style="color: #DCDCAA">run</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">t2</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;jdbc:oracle:oci:@odb&quot;</span></span>
<span class="line"><span style="color: #DCDCAA">run</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">t3</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;jdbc:oracle:oci:@odb&quot;</span></span>
<span class="line"><span style="color: #DCDCAA">run</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">t4</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;jdbc:oracle:oci:@odb&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955"># OCI driver without Oracle*Net</span></span>
<span class="line"><span style="color: #DCDCAA">run</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">t1</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;jdbc:oracle:oci:@&quot;</span></span>
<span class="line"><span style="color: #DCDCAA">run</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">t2</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;jdbc:oracle:oci:@&quot;</span></span>
<span class="line"><span style="color: #DCDCAA">run</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">t3</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;jdbc:oracle:oci:@&quot;</span></span>
<span class="line"><span style="color: #DCDCAA">run</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">t4</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;jdbc:oracle:oci:@&quot;</span></span></code></pre></div>



<h2 class="wp-block-heading">The Result</h2>



<p>Here&#8217;s the output of the <code>run.sh</code> call:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Console output of run.sh</span><span role="button" tabindex="0" data-code="[oracle@odb180 lib]$ ./run.sh
run #1: read 100000 rows from t1 in 11.918 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.
run #2: read 100000 rows from t1 in 11.625 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.
run #3: read 100000 rows from t1 in 11.662 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.
run #4: read 100000 rows from t1 in 11.574 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.
run #5: read 100000 rows from t1 in 11.729 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.

run #1: read 100000 rows from t2 in 11.786 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.
run #2: read 100000 rows from t2 in 12.071 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.
run #3: read 100000 rows from t2 in 12.621 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.
run #4: read 100000 rows from t2 in 11.913 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.
run #5: read 100000 rows from t2 in 11.972 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.

run #1: read 100000 rows from t3 in 11.397 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.
run #2: read 100000 rows from t3 in 11.429 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.
run #3: read 100000 rows from t3 in 11.308 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.
run #4: read 100000 rows from t3 in 11.793 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.
run #5: read 100000 rows from t3 in 11.903 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.

run #1: read 100000 rows from t4 in 19.789 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.
run #2: read 100000 rows from t4 in 19.461 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.
run #3: read 100000 rows from t4 in 19.181 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.
run #4: read 100000 rows from t4 in 19.211 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.
run #5: read 100000 rows from t4 in 19.242 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.

run #1: read 100000 rows from t1 in 13.145 seconds via jdbc:oracle:oci:@odb.
run #2: read 100000 rows from t1 in 12.698 seconds via jdbc:oracle:oci:@odb.
run #3: read 100000 rows from t1 in 13.14 seconds via jdbc:oracle:oci:@odb.
run #4: read 100000 rows from t1 in 12.842 seconds via jdbc:oracle:oci:@odb.
run #5: read 100000 rows from t1 in 12.978 seconds via jdbc:oracle:oci:@odb.

run #1: read 100000 rows from t2 in 13.049 seconds via jdbc:oracle:oci:@odb.
run #2: read 100000 rows from t2 in 12.581 seconds via jdbc:oracle:oci:@odb.
run #3: read 100000 rows from t2 in 12.44 seconds via jdbc:oracle:oci:@odb.
run #4: read 100000 rows from t2 in 12.787 seconds via jdbc:oracle:oci:@odb.
run #5: read 100000 rows from t2 in 12.727 seconds via jdbc:oracle:oci:@odb.

run #1: read 100000 rows from t3 in 12.402 seconds via jdbc:oracle:oci:@odb.
run #2: read 100000 rows from t3 in 12.479 seconds via jdbc:oracle:oci:@odb.
run #3: read 100000 rows from t3 in 12.483 seconds via jdbc:oracle:oci:@odb.
run #4: read 100000 rows from t3 in 12.346 seconds via jdbc:oracle:oci:@odb.
run #5: read 100000 rows from t3 in 12.528 seconds via jdbc:oracle:oci:@odb.

run #1: read 100000 rows from t4 in 11.452 seconds via jdbc:oracle:oci:@odb.
run #2: read 100000 rows from t4 in 10.945 seconds via jdbc:oracle:oci:@odb.
run #3: read 100000 rows from t4 in 11.597 seconds via jdbc:oracle:oci:@odb.
run #4: read 100000 rows from t4 in 11.295 seconds via jdbc:oracle:oci:@odb.
run #5: read 100000 rows from t4 in 11.746 seconds via jdbc:oracle:oci:@odb.

run #1: read 100000 rows from t1 in 10.508 seconds via jdbc:oracle:oci:@.
run #2: read 100000 rows from t1 in 10.662 seconds via jdbc:oracle:oci:@.
run #3: read 100000 rows from t1 in 10.105 seconds via jdbc:oracle:oci:@.
run #4: read 100000 rows from t1 in 10.44 seconds via jdbc:oracle:oci:@.
run #5: read 100000 rows from t1 in 10.415 seconds via jdbc:oracle:oci:@.

run #1: read 100000 rows from t2 in 10.29 seconds via jdbc:oracle:oci:@.
run #2: read 100000 rows from t2 in 10.15 seconds via jdbc:oracle:oci:@.
run #3: read 100000 rows from t2 in 10.266 seconds via jdbc:oracle:oci:@.
run #4: read 100000 rows from t2 in 10.351 seconds via jdbc:oracle:oci:@.
run #5: read 100000 rows from t2 in 10.259 seconds via jdbc:oracle:oci:@.

run #1: read 100000 rows from t3 in 9.95 seconds via jdbc:oracle:oci:@.
run #2: read 100000 rows from t3 in 9.756 seconds via jdbc:oracle:oci:@.
run #3: read 100000 rows from t3 in 10.325 seconds via jdbc:oracle:oci:@.
run #4: read 100000 rows from t3 in 9.517 seconds via jdbc:oracle:oci:@.
run #5: read 100000 rows from t3 in 9.951 seconds via jdbc:oracle:oci:@.

run #1: read 100000 rows from t4 in 9.182 seconds via jdbc:oracle:oci:@.
run #2: read 100000 rows from t4 in 8.996 seconds via jdbc:oracle:oci:@.
run #3: read 100000 rows from t4 in 8.977 seconds via jdbc:oracle:oci:@.
run #4: read 100000 rows from t4 in 9.024 seconds via jdbc:oracle:oci:@.
run #5: read 100000 rows from t4 in 9.082 seconds via jdbc:oracle:oci:@." style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">[oracle@odb180 lib]$ ./run.sh</span></span>
<span class="line"><span style="color: #D4D4D4">run #1: read 100000 rows from t1 in 11.918 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.</span></span>
<span class="line"><span style="color: #D4D4D4">run #2: read 100000 rows from t1 in 11.625 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.</span></span>
<span class="line"><span style="color: #D4D4D4">run #3: read 100000 rows from t1 in 11.662 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.</span></span>
<span class="line"><span style="color: #D4D4D4">run #4: read 100000 rows from t1 in 11.574 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.</span></span>
<span class="line"><span style="color: #D4D4D4">run #5: read 100000 rows from t1 in 11.729 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">run #1: read 100000 rows from t2 in 11.786 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.</span></span>
<span class="line"><span style="color: #D4D4D4">run #2: read 100000 rows from t2 in 12.071 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.</span></span>
<span class="line"><span style="color: #D4D4D4">run #3: read 100000 rows from t2 in 12.621 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.</span></span>
<span class="line"><span style="color: #D4D4D4">run #4: read 100000 rows from t2 in 11.913 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.</span></span>
<span class="line"><span style="color: #D4D4D4">run #5: read 100000 rows from t2 in 11.972 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">run #1: read 100000 rows from t3 in 11.397 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.</span></span>
<span class="line"><span style="color: #D4D4D4">run #2: read 100000 rows from t3 in 11.429 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.</span></span>
<span class="line"><span style="color: #D4D4D4">run #3: read 100000 rows from t3 in 11.308 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.</span></span>
<span class="line"><span style="color: #D4D4D4">run #4: read 100000 rows from t3 in 11.793 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.</span></span>
<span class="line"><span style="color: #D4D4D4">run #5: read 100000 rows from t3 in 11.903 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">run #1: read 100000 rows from t4 in 19.789 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.</span></span>
<span class="line"><span style="color: #D4D4D4">run #2: read 100000 rows from t4 in 19.461 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.</span></span>
<span class="line"><span style="color: #D4D4D4">run #3: read 100000 rows from t4 in 19.181 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.</span></span>
<span class="line"><span style="color: #D4D4D4">run #4: read 100000 rows from t4 in 19.211 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.</span></span>
<span class="line"><span style="color: #D4D4D4">run #5: read 100000 rows from t4 in 19.242 seconds via jdbc:oracle:thin:@//localhost:1521/odb.docker.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">run #1: read 100000 rows from t1 in 13.145 seconds via jdbc:oracle:oci:@odb.</span></span>
<span class="line"><span style="color: #D4D4D4">run #2: read 100000 rows from t1 in 12.698 seconds via jdbc:oracle:oci:@odb.</span></span>
<span class="line"><span style="color: #D4D4D4">run #3: read 100000 rows from t1 in 13.14 seconds via jdbc:oracle:oci:@odb.</span></span>
<span class="line"><span style="color: #D4D4D4">run #4: read 100000 rows from t1 in 12.842 seconds via jdbc:oracle:oci:@odb.</span></span>
<span class="line"><span style="color: #D4D4D4">run #5: read 100000 rows from t1 in 12.978 seconds via jdbc:oracle:oci:@odb.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">run #1: read 100000 rows from t2 in 13.049 seconds via jdbc:oracle:oci:@odb.</span></span>
<span class="line"><span style="color: #D4D4D4">run #2: read 100000 rows from t2 in 12.581 seconds via jdbc:oracle:oci:@odb.</span></span>
<span class="line"><span style="color: #D4D4D4">run #3: read 100000 rows from t2 in 12.44 seconds via jdbc:oracle:oci:@odb.</span></span>
<span class="line"><span style="color: #D4D4D4">run #4: read 100000 rows from t2 in 12.787 seconds via jdbc:oracle:oci:@odb.</span></span>
<span class="line"><span style="color: #D4D4D4">run #5: read 100000 rows from t2 in 12.727 seconds via jdbc:oracle:oci:@odb.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">run #1: read 100000 rows from t3 in 12.402 seconds via jdbc:oracle:oci:@odb.</span></span>
<span class="line"><span style="color: #D4D4D4">run #2: read 100000 rows from t3 in 12.479 seconds via jdbc:oracle:oci:@odb.</span></span>
<span class="line"><span style="color: #D4D4D4">run #3: read 100000 rows from t3 in 12.483 seconds via jdbc:oracle:oci:@odb.</span></span>
<span class="line"><span style="color: #D4D4D4">run #4: read 100000 rows from t3 in 12.346 seconds via jdbc:oracle:oci:@odb.</span></span>
<span class="line"><span style="color: #D4D4D4">run #5: read 100000 rows from t3 in 12.528 seconds via jdbc:oracle:oci:@odb.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">run #1: read 100000 rows from t4 in 11.452 seconds via jdbc:oracle:oci:@odb.</span></span>
<span class="line"><span style="color: #D4D4D4">run #2: read 100000 rows from t4 in 10.945 seconds via jdbc:oracle:oci:@odb.</span></span>
<span class="line"><span style="color: #D4D4D4">run #3: read 100000 rows from t4 in 11.597 seconds via jdbc:oracle:oci:@odb.</span></span>
<span class="line"><span style="color: #D4D4D4">run #4: read 100000 rows from t4 in 11.295 seconds via jdbc:oracle:oci:@odb.</span></span>
<span class="line"><span style="color: #D4D4D4">run #5: read 100000 rows from t4 in 11.746 seconds via jdbc:oracle:oci:@odb.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">run #1: read 100000 rows from t1 in 10.508 seconds via jdbc:oracle:oci:@.</span></span>
<span class="line"><span style="color: #D4D4D4">run #2: read 100000 rows from t1 in 10.662 seconds via jdbc:oracle:oci:@.</span></span>
<span class="line"><span style="color: #D4D4D4">run #3: read 100000 rows from t1 in 10.105 seconds via jdbc:oracle:oci:@.</span></span>
<span class="line"><span style="color: #D4D4D4">run #4: read 100000 rows from t1 in 10.44 seconds via jdbc:oracle:oci:@.</span></span>
<span class="line"><span style="color: #D4D4D4">run #5: read 100000 rows from t1 in 10.415 seconds via jdbc:oracle:oci:@.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">run #1: read 100000 rows from t2 in 10.29 seconds via jdbc:oracle:oci:@.</span></span>
<span class="line"><span style="color: #D4D4D4">run #2: read 100000 rows from t2 in 10.15 seconds via jdbc:oracle:oci:@.</span></span>
<span class="line"><span style="color: #D4D4D4">run #3: read 100000 rows from t2 in 10.266 seconds via jdbc:oracle:oci:@.</span></span>
<span class="line"><span style="color: #D4D4D4">run #4: read 100000 rows from t2 in 10.351 seconds via jdbc:oracle:oci:@.</span></span>
<span class="line"><span style="color: #D4D4D4">run #5: read 100000 rows from t2 in 10.259 seconds via jdbc:oracle:oci:@.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">run #1: read 100000 rows from t3 in 9.95 seconds via jdbc:oracle:oci:@.</span></span>
<span class="line"><span style="color: #D4D4D4">run #2: read 100000 rows from t3 in 9.756 seconds via jdbc:oracle:oci:@.</span></span>
<span class="line"><span style="color: #D4D4D4">run #3: read 100000 rows from t3 in 10.325 seconds via jdbc:oracle:oci:@.</span></span>
<span class="line"><span style="color: #D4D4D4">run #4: read 100000 rows from t3 in 9.517 seconds via jdbc:oracle:oci:@.</span></span>
<span class="line"><span style="color: #D4D4D4">run #5: read 100000 rows from t3 in 9.951 seconds via jdbc:oracle:oci:@.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">run #1: read 100000 rows from t4 in 9.182 seconds via jdbc:oracle:oci:@.</span></span>
<span class="line"><span style="color: #D4D4D4">run #2: read 100000 rows from t4 in 8.996 seconds via jdbc:oracle:oci:@.</span></span>
<span class="line"><span style="color: #D4D4D4">run #3: read 100000 rows from t4 in 8.977 seconds via jdbc:oracle:oci:@.</span></span>
<span class="line"><span style="color: #D4D4D4">run #4: read 100000 rows from t4 in 9.024 seconds via jdbc:oracle:oci:@.</span></span>
<span class="line"><span style="color: #D4D4D4">run #5: read 100000 rows from t4 in 9.082 seconds via jdbc:oracle:oci:@.</span></span></code></pre></div>



<p>As in my previous post, I ignore the slowest and fastest run and take the average of the remaining three results per test variant to produce a chart.</p>



<figure class="wp-block-image"><a href="https://www.salvis.com/blog/wp-content/uploads/2018/06/Performance.png"><img decoding="async" width="1010" height="614" src="https://www.salvis.com/blog/wp-content/uploads/2018/06/Performance.png" alt="" class="wp-image-8506" srcset="https://www.salvis.com/blog/wp-content/uploads/2018/06/Performance.png 1010w, https://www.salvis.com/blog/wp-content/uploads/2018/06/Performance-300x182.png 300w, https://www.salvis.com/blog/wp-content/uploads/2018/06/Performance-768x467.png 768w, https://www.salvis.com/blog/wp-content/uploads/2018/06/Performance-240x146.png 240w, https://www.salvis.com/blog/wp-content/uploads/2018/06/Performance-50x30.png 50w, https://www.salvis.com/blog/wp-content/uploads/2018/06/Performance-123x75.png 123w" sizes="(max-width:767px) 480px, (max-width:1010px) 100vw, 1010px" /></a></figure>



<p>We see that using the JDBC OCI driver delivers the fastest results when skipping Oracle Net. Furthermore, the MemOptimized RowStore delivers the fastest results via OCI. Accessing the MemOptimized RowStore via the JDBC thin driver leads by to a bad performance. This looks like a bug.</p>



<h2 class="wp-block-heading">Conclusion</h2>



<p>To get benefit from the MemOptimized RowStore you have to access the database via OCI.</p>
<p>The post <a href="https://www.salvis.com/blog/2018/06/19/memoptimized-rowstore-in-oracle-database-18c-with-oci/">MemOptimized RowStore in Oracle Database 18c with OCI</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.salvis.com/blog/2018/06/19/memoptimized-rowstore-in-oracle-database-18c-with-oci/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
	</channel>
</rss>
