<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	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/"
		>
<channel>
	<title>Comments on: Alternatives to using a job?</title>
	<atom:link href="http://oraqa.com/2006/01/17/alternatives-to-using-a-job/feed/" rel="self" type="application/rss+xml" />
	<link>http://oraqa.com/2006/01/17/alternatives-to-using-a-job/</link>
	<description>Oracle Question and Answer</description>
	<lastBuildDate>Tue, 06 Jul 2010 14:28:12 -0600</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
		<item>
		<title>By: DaPi</title>
		<link>http://oraqa.com/2006/01/17/alternatives-to-using-a-job/comment-page-1/#comment-77</link>
		<dc:creator>DaPi</dc:creator>
		<pubDate>Sun, 22 Jan 2006 09:39:34 +0000</pubDate>
		<guid isPermaLink="false">http://oraqa.com/2006/01/17/alternatives-to-using-a-job/#comment-77</guid>
		<description>WTF?  &lt;i&gt;One other thing you could do is when you begin your transaction, insert a dummy record into the t_inventoy table. Just issue some update statement against it. The table will be locked from updates but can still be read from. After the operation is commited all the changes that were waiting during the lock will then happen upon the table. This way you should not lose any records.&lt;/i&gt;

Not if we are still talking about Oracle.</description>
		<content:encoded><![CDATA[<p>WTF?  <i>One other thing you could do is when you begin your transaction, insert a dummy record into the t_inventoy table. Just issue some update statement against it. The table will be locked from updates but can still be read from. After the operation is commited all the changes that were waiting during the lock will then happen upon the table. This way you should not lose any records.</i></p>
<p>Not if we are still talking about Oracle.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Eddie Awad</title>
		<link>http://oraqa.com/2006/01/17/alternatives-to-using-a-job/comment-page-1/#comment-62</link>
		<dc:creator>Eddie Awad</dc:creator>
		<pubDate>Wed, 18 Jan 2006 19:35:01 +0000</pubDate>
		<guid isPermaLink="false">http://oraqa.com/2006/01/17/alternatives-to-using-a-job/#comment-62</guid>
		<description>David, I did close the pre tag for you. 

I will have to add some kind of &quot;comment preview&quot; functionality to the site. 

Thanks.</description>
		<content:encoded><![CDATA[<p>David, I did close the pre tag for you. </p>
<p>I will have to add some kind of &#8220;comment preview&#8221; functionality to the site. </p>
<p>Thanks.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: David Aldridge</title>
		<link>http://oraqa.com/2006/01/17/alternatives-to-using-a-job/comment-page-1/#comment-61</link>
		<dc:creator>David Aldridge</dc:creator>
		<pubDate>Wed, 18 Jan 2006 19:25:49 +0000</pubDate>
		<guid isPermaLink="false">http://oraqa.com/2006/01/17/alternatives-to-using-a-job/#comment-61</guid>
		<description>OOp -- forgot to close the pre tag</description>
		<content:encoded><![CDATA[<p>OOp &#8212; forgot to close the pre tag</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: David Aldridge</title>
		<link>http://oraqa.com/2006/01/17/alternatives-to-using-a-job/comment-page-1/#comment-60</link>
		<dc:creator>David Aldridge</dc:creator>
		<pubDate>Wed, 18 Jan 2006 19:25:01 +0000</pubDate>
		<guid isPermaLink="false">http://oraqa.com/2006/01/17/alternatives-to-using-a-job/#comment-60</guid>
		<description>In that case ...


Tim,

The underlying problem here probably is that the performance in scanning a table of inventory transactions to calculate the balance is poor, so here&#039;s some thoughts on that.

Firstly, I like the MV idea. There&#039;s a certain risk in adopting it because you are potentially using code paths in the RDBMS that you haven&#039;t used before, so your exposure to bugs in the Oracle code is higher. You might have trouble if you need to archive old transactions.

Secondly, if you want to calculate balances for a particular item based on inventory transactions then clustering the transactions together would be one option. Putting the table into a hash cluster based on the item identifier would do this nicely -- again, new code paths being used.

Thirdly, you could adopt a hybrid strategy of calculating balances based on an intermittently-maintained balance table and a subset of your transactions ... you might define the balance table as ...

&lt;pre&gt;ITEM#
AS_OF_DATE
BALANCE_QTY&lt;/pre&gt;

.. and populate it as ...

&lt;pre&gt;SELECT
   ITEM#,
   MAX(TRANSACTION_DATE),
   SUM(BALANCE_CHANGE_QTY)
FROM
   INVENTORY_TRANSACTIONS
GROUP BY
   ITEM#
&lt;/pre&gt;

You&#039;d maybe want to update the balance table at 3am using a predicate such as ...
&lt;pre&gt;TRANSACTION_DATE&lt;/pre&gt;

... and then calculate the current balance based on a query like ...

&lt;pre&gt;
SELECT
   ITEM#,
   BALANCE_QTY+
   (SELECT SUM(BALANCE_CHANGE_QTY)
    FROM   INVENTORY_TRANSACTIONS IT
    WHERE  IT.ITEM# = IB.ITEM# AND
           TRANSACTION_DATE &gt; IB.AS_OF_DATE)
FROM
   INVENTORY_BALANCE IB
WHERE
   ITEM# = 12345
&lt;/pre&gt;

This would allow you to archive inventory transactions, or reduce the amount of work required to calculate the balance dynamically if you had a very high number of transactions and you could efficiently query a subset of them by ITEM# and semi-bounded range of TRANSACTION_DATE.

This third strategy also extends to allowing manual adjustments to the inventory balance in another table -- the world being what it is one often finds that balances are not what they should be.</description>
		<content:encoded><![CDATA[<p>In that case &#8230;</p>
<p>Tim,</p>
<p>The underlying problem here probably is that the performance in scanning a table of inventory transactions to calculate the balance is poor, so here&#8217;s some thoughts on that.</p>
<p>Firstly, I like the MV idea. There&#8217;s a certain risk in adopting it because you are potentially using code paths in the RDBMS that you haven&#8217;t used before, so your exposure to bugs in the Oracle code is higher. You might have trouble if you need to archive old transactions.</p>
<p>Secondly, if you want to calculate balances for a particular item based on inventory transactions then clustering the transactions together would be one option. Putting the table into a hash cluster based on the item identifier would do this nicely &#8212; again, new code paths being used.</p>
<p>Thirdly, you could adopt a hybrid strategy of calculating balances based on an intermittently-maintained balance table and a subset of your transactions &#8230; you might define the balance table as &#8230;</p>
<pre>ITEM#
AS_OF_DATE
BALANCE_QTY</pre>
<p>.. and populate it as &#8230;</p>
<pre>SELECT
   ITEM#,
   MAX(TRANSACTION_DATE),
   SUM(BALANCE_CHANGE_QTY)
FROM
   INVENTORY_TRANSACTIONS
GROUP BY
   ITEM#
</pre>
<p>You&#8217;d maybe want to update the balance table at 3am using a predicate such as &#8230;</p>
<pre>TRANSACTION_DATE</pre>
<p>&#8230; and then calculate the current balance based on a query like &#8230;</p>
<pre>
SELECT
   ITEM#,
   BALANCE_QTY+
   (SELECT SUM(BALANCE_CHANGE_QTY)
    FROM   INVENTORY_TRANSACTIONS IT
    WHERE  IT.ITEM# = IB.ITEM# AND
           TRANSACTION_DATE &gt; IB.AS_OF_DATE)
FROM
   INVENTORY_BALANCE IB
WHERE
   ITEM# = 12345
</pre>
<p>This would allow you to archive inventory transactions, or reduce the amount of work required to calculate the balance dynamically if you had a very high number of transactions and you could efficiently query a subset of them by ITEM# and semi-bounded range of TRANSACTION_DATE.</p>
<p>This third strategy also extends to allowing manual adjustments to the inventory balance in another table &#8212; the world being what it is one often finds that balances are not what they should be.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: timboc</title>
		<link>http://oraqa.com/2006/01/17/alternatives-to-using-a-job/comment-page-1/#comment-58</link>
		<dc:creator>timboc</dc:creator>
		<pubDate>Wed, 18 Jan 2006 18:40:53 +0000</pubDate>
		<guid isPermaLink="false">http://oraqa.com/2006/01/17/alternatives-to-using-a-job/#comment-58</guid>
		<description>I appreciate everyones input into my question, it&#039;s certainly given me some &quot;food for thought&quot;.

I also have a better understanding as to what types of questions are appropriate for this site as well.

-Tim</description>
		<content:encoded><![CDATA[<p>I appreciate everyones input into my question, it&#8217;s certainly given me some &#8220;food for thought&#8221;.</p>
<p>I also have a better understanding as to what types of questions are appropriate for this site as well.</p>
<p>-Tim</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Eddie Awad</title>
		<link>http://oraqa.com/2006/01/17/alternatives-to-using-a-job/comment-page-1/#comment-57</link>
		<dc:creator>Eddie Awad</dc:creator>
		<pubDate>Wed, 18 Jan 2006 18:35:07 +0000</pubDate>
		<guid isPermaLink="false">http://oraqa.com/2006/01/17/alternatives-to-using-a-job/#comment-57</guid>
		<description>&lt;i&gt;If it was up to me Iâ€™d delete the question and redirect the OP to a forum&lt;/i&gt;
I won&#039;t delete it, but this will be the first and last time I approve such questions (as I mentioned why in comment number 2 above).

&lt;i&gt;you might like to see if you can put a warning on the â€œAsk a new questionâ€ page to warn against specific question&lt;/i&gt;
Great suggestion. The About page answers exactly what type of questions and answers should be submitted, however, I will look into adding such warning on the &quot;new post&quot; page as well.</description>
		<content:encoded><![CDATA[<p><i>If it was up to me Iâ€™d delete the question and redirect the OP to a forum</i><br />
I won&#8217;t delete it, but this will be the first and last time I approve such questions (as I mentioned why in comment number 2 above).</p>
<p><i>you might like to see if you can put a warning on the â€œAsk a new questionâ€ page to warn against specific question</i><br />
Great suggestion. The About page answers exactly what type of questions and answers should be submitted, however, I will look into adding such warning on the &#8220;new post&#8221; page as well.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: troach</title>
		<link>http://oraqa.com/2006/01/17/alternatives-to-using-a-job/comment-page-1/#comment-56</link>
		<dc:creator>troach</dc:creator>
		<pubDate>Wed, 18 Jan 2006 17:35:41 +0000</pubDate>
		<guid isPermaLink="false">http://oraqa.com/2006/01/17/alternatives-to-using-a-job/#comment-56</guid>
		<description>One other thing you could do is when you begin your transaction, insert a dummy record into the t_inventoy table. Just issue some update statement against it. The table will be locked from updates but can still be read from. After the operation is commited all the changes that were waiting during the lock will then happen upon the table. This way you should not lose any records.</description>
		<content:encoded><![CDATA[<p>One other thing you could do is when you begin your transaction, insert a dummy record into the t_inventoy table. Just issue some update statement against it. The table will be locked from updates but can still be read from. After the operation is commited all the changes that were waiting during the lock will then happen upon the table. This way you should not lose any records.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: troach</title>
		<link>http://oraqa.com/2006/01/17/alternatives-to-using-a-job/comment-page-1/#comment-54</link>
		<dc:creator>troach</dc:creator>
		<pubDate>Wed, 18 Jan 2006 16:49:33 +0000</pubDate>
		<guid isPermaLink="false">http://oraqa.com/2006/01/17/alternatives-to-using-a-job/#comment-54</guid>
		<description>timboc, I agree with David.

But I answered your question. Just use a plain view with the group by. You can then use it in all of your other SQL. It&#039;s not an inline or materialized.

Do you know what you&#039;re doing? I think you are over complicating a simple task.

The table is there, just make a view using a group by. Simple enough. No Meterialized needed unless you end up with a huge table. To keep the table small I would do this perhaps.

DROP TABLE t_inventory_temp;

CREATE TABLE t_inventory_temp
AS SELECT * from t_inventory;

DELETE FROM t_inventory;

INSERT INTO t_inventory
SELECT product_id, sum(in_stock)
FROM t_inventory_temp;

(I would not drop t_inventory_temp as it could also be a temporary backup location. Nice to have for troubleshooting purposes etc.)

You&#039;re done. Maybe reindex here?

That&#039;s pretty simple and keeps the table small.</description>
		<content:encoded><![CDATA[<p>timboc, I agree with David.</p>
<p>But I answered your question. Just use a plain view with the group by. You can then use it in all of your other SQL. It&#8217;s not an inline or materialized.</p>
<p>Do you know what you&#8217;re doing? I think you are over complicating a simple task.</p>
<p>The table is there, just make a view using a group by. Simple enough. No Meterialized needed unless you end up with a huge table. To keep the table small I would do this perhaps.</p>
<p>DROP TABLE t_inventory_temp;</p>
<p>CREATE TABLE t_inventory_temp<br />
AS SELECT * from t_inventory;</p>
<p>DELETE FROM t_inventory;</p>
<p>INSERT INTO t_inventory<br />
SELECT product_id, sum(in_stock)<br />
FROM t_inventory_temp;</p>
<p>(I would not drop t_inventory_temp as it could also be a temporary backup location. Nice to have for troubleshooting purposes etc.)</p>
<p>You&#8217;re done. Maybe reindex here?</p>
<p>That&#8217;s pretty simple and keeps the table small.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: David Aldridge</title>
		<link>http://oraqa.com/2006/01/17/alternatives-to-using-a-job/comment-page-1/#comment-53</link>
		<dc:creator>David Aldridge</dc:creator>
		<pubDate>Wed, 18 Jan 2006 14:35:40 +0000</pubDate>
		<guid isPermaLink="false">http://oraqa.com/2006/01/17/alternatives-to-using-a-job/#comment-53</guid>
		<description>Eddie,

If it was up to me I&#039;d delete the question and redirect the OP to a forum -- you might like to see if you can put a warning on the &quot;Ask a new question&quot; page to warn against specific question (or is there already one?), similar in purpose to the &quot;Fair Warning&quot; on AskTom.</description>
		<content:encoded><![CDATA[<p>Eddie,</p>
<p>If it was up to me I&#8217;d delete the question and redirect the OP to a forum &#8212; you might like to see if you can put a warning on the &#8220;Ask a new question&#8221; page to warn against specific question (or is there already one?), similar in purpose to the &#8220;Fair Warning&#8221; on AskTom.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: timboc</title>
		<link>http://oraqa.com/2006/01/17/alternatives-to-using-a-job/comment-page-1/#comment-47</link>
		<dc:creator>timboc</dc:creator>
		<pubDate>Wed, 18 Jan 2006 13:12:17 +0000</pubDate>
		<guid isPermaLink="false">http://oraqa.com/2006/01/17/alternatives-to-using-a-job/#comment-47</guid>
		<description>The issue with a materialized view is that there are too many transactions being posted to this table to make it useful (in my honest opinion).

I&#039;ll further my original post with more details to hopefully make it clear what I&#039;m doing.

1. My &quot;in stock&quot; table is named t_inventory (product_id, in_stock)
2. I can see the current &quot;in stock&quot; by selecting a single row from this table by using it&#039;s product_id.
3. t_inventory has an index on product_id
4. When a transaction that affects &quot;in stock&quot; is committed I place a row in t_inventory_queue (product_id, in_stock_change), which contains the product_id and the amount to increment or decrement &quot;in stock&quot;
5. I have a job in my database that runs every minute and takes the changes from t_inventory_queue and updates (or inserts) rows in t_inventory, it then deletes the row from t_inventory_queue.

The benefit of the t_inventory approach (instead of doing a select sum() with a group by) is that in much of my application I can include t_inventory right in my SQL FROM clauses, instead of having to do inline views or call stored functions, since I&#039;ll only have a single row for any product_id.

As I mentioned before, the two downsides are:

1. The DBA drops the job, the job breaks (it could but I&#039;ve never seen it happen in my schema) or the job never runs or runs too infrequently (job_queue_interval and job_queue_processes).

2. With the job running every 60 seconds the worst case scenario is that others won&#039;t see the true &quot;in stock&quot; values for up to a minute.


One of my thoughts was to run the job more frequently (every 15 seconds).  I know that in Oracle8i you have access to job_queue_interval but that isn&#039;t available any more in 9i.  Does anyone know how often the job queue is checked in 9i and above?

I&#039;ve read just a little about advanced queues, I&#039;m not sure if that is appropriate or not.  It seems to me that if the &quot;job&quot; I&#039;m currently running could be run immediately if there are rows committed to t_inventory_queue that would be ideal.  The key is that only a single process ever processes rows from t_inventory_queue (something Oracle&#039;s job functionality does for me right now).

-Tim</description>
		<content:encoded><![CDATA[<p>The issue with a materialized view is that there are too many transactions being posted to this table to make it useful (in my honest opinion).</p>
<p>I&#8217;ll further my original post with more details to hopefully make it clear what I&#8217;m doing.</p>
<p>1. My &#8220;in stock&#8221; table is named t_inventory (product_id, in_stock)<br />
2. I can see the current &#8220;in stock&#8221; by selecting a single row from this table by using it&#8217;s product_id.<br />
3. t_inventory has an index on product_id<br />
4. When a transaction that affects &#8220;in stock&#8221; is committed I place a row in t_inventory_queue (product_id, in_stock_change), which contains the product_id and the amount to increment or decrement &#8220;in stock&#8221;<br />
5. I have a job in my database that runs every minute and takes the changes from t_inventory_queue and updates (or inserts) rows in t_inventory, it then deletes the row from t_inventory_queue.</p>
<p>The benefit of the t_inventory approach (instead of doing a select sum() with a group by) is that in much of my application I can include t_inventory right in my SQL FROM clauses, instead of having to do inline views or call stored functions, since I&#8217;ll only have a single row for any product_id.</p>
<p>As I mentioned before, the two downsides are:</p>
<p>1. The DBA drops the job, the job breaks (it could but I&#8217;ve never seen it happen in my schema) or the job never runs or runs too infrequently (job_queue_interval and job_queue_processes).</p>
<p>2. With the job running every 60 seconds the worst case scenario is that others won&#8217;t see the true &#8220;in stock&#8221; values for up to a minute.</p>
<p>One of my thoughts was to run the job more frequently (every 15 seconds).  I know that in Oracle8i you have access to job_queue_interval but that isn&#8217;t available any more in 9i.  Does anyone know how often the job queue is checked in 9i and above?</p>
<p>I&#8217;ve read just a little about advanced queues, I&#8217;m not sure if that is appropriate or not.  It seems to me that if the &#8220;job&#8221; I&#8217;m currently running could be run immediately if there are rows committed to t_inventory_queue that would be ideal.  The key is that only a single process ever processes rows from t_inventory_queue (something Oracle&#8217;s job functionality does for me right now).</p>
<p>-Tim</p>
]]></content:encoded>
	</item>
</channel>
</rss>
