<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;DUAMSX8-eyp7ImA9WhRRFE4.&quot;"><id>tag:blogger.com,1999:blog-359699111496312090</id><updated>2011-11-27T15:49:48.153-08:00</updated><title>OBIEE (Oracle Business Intelligence - Enterprise Edition)</title><subtitle type="html" /><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://navi-obiee.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://navi-obiee.blogspot.com/" /><author><name>Mash</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>11</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/blogspot/ELxJo" /><feedburner:info uri="blogspot/elxjo" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;D04NRHcyfyp7ImA9Wx9UEU0.&quot;"><id>tag:blogger.com,1999:blog-359699111496312090.post-6770471491613951012</id><published>2010-12-12T17:08:00.000-08:00</published><updated>2011-02-07T11:13:15.997-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-02-07T11:13:15.997-08:00</app:edited><title>Connection Pooling and Sizing of Connection Pools</title><content type="html">&lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;A question that does not get asked as often as it should is what is the best size for a connection pool to a database. However, the answer to that question can have a major impact the response times your users experience as well as the throughput of the system.&lt;/p&gt;  &lt;p&gt;Luckily for us, a number of people on the internet have provided a simple answer to that question for different technologies – “It Depends!”.&lt;/p&gt;  &lt;p&gt;&lt;a title="http://dev.mysql.com/tech-resources/articles/connection_pooling_with_connectorj.html" href="http://dev.mysql.com/tech-resources/articles/connection_pooling_with_connectorj.html"&gt;http://dev.mysql.com/tech-resources/articles/connection_pooling_with_connectorj.html&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a title="http://searchdomino.techtarget.com/expert/KnowledgebaseAnswer/0,289625,sid4_gci851755,00.html" href="http://searchdomino.techtarget.com/expert/KnowledgebaseAnswer/0,289625,sid4_gci851755,00.html"&gt;http://searchdomino.techtarget.com/expert/KnowledgebaseAnswer/0,289625,sid4_gci851755,00.html&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a title="http://stackoverflow.com/questions/405352/mysql-connection-pooling-question-is-it-worth-it" href="http://stackoverflow.com/questions/405352/mysql-connection-pooling-question-is-it-worth-it"&gt;http://stackoverflow.com/questions/405352/mysql-connection-pooling-question-is-it-worth-it&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;So, let us talk about what are the factors to take into consideration when planning the optimal size of the connection pool.&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;A connection pool that is too small means that queries have to wait to get a connection before they execute. This delay can be quite large – in seconds – for a loaded system &lt;/li&gt;    &lt;li&gt;A very large connection pool, on the other hand has its own problems      &lt;ul&gt;       &lt;li&gt;First of all, connection pools are fairly heavy in terms of memory usage. This will impact the memory OBIEE server uses, which may or may not be a concern depending on whether you are on a 64-bit platform, and the available RAM. &lt;/li&gt;        &lt;li&gt;Secondly, if you have a large connection pool, all queries will be sent on to the database. Your database box and/or disk will see a performance degradation beyond their capacity. &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;That means you need two pieces of information to correctly size the connection pool – the database capacity for parallelism and the expected concurrency. The former typically depends on the database you run, the machine specs, and the operating system. Your DBA will be able to help determine this based on his past experience. Think of this as the “supply” of connections.&lt;/p&gt;  &lt;p&gt;Here is a little spreadsheet to help determine the “demand” for connections. The numbers here are, of course, made up for illustration only:&lt;/p&gt;  &lt;table border="1" cellspacing="0" cellpadding="2" width="400"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td valign="top" width="207"&gt;Name of Factor&lt;/td&gt;        &lt;td valign="top" width="59"&gt;Number&lt;/td&gt;        &lt;td valign="top" width="133"&gt;Cumulative Effect&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="207"&gt;No of Named Users&lt;/td&gt;        &lt;td valign="top" width="59"&gt;5000&lt;/td&gt;        &lt;td valign="top" width="133"&gt;5000&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="207"&gt;% logged on at peak times&lt;/td&gt;        &lt;td valign="top" width="59"&gt;10%&lt;/td&gt;        &lt;td valign="top" width="133"&gt;500&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="207"&gt;No. of reports on a dashboard&lt;/td&gt;        &lt;td valign="top" width="59"&gt;10&lt;/td&gt;        &lt;td valign="top" width="133"&gt;5000&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="207"&gt;% time running a dash board – For example, if a dash board runs in 5 seconds, and think time between runs is 30s – this is (5)/(5+30)&lt;/td&gt;        &lt;td valign="top" width="59"&gt;14%&lt;/td&gt;        &lt;td valign="top" width="133"&gt;714&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="207"&gt;Cache Miss Ratio – This will be high for highly customized reports&lt;/td&gt;        &lt;td valign="top" width="59"&gt;80%&lt;/td&gt;        &lt;td valign="top" width="133"&gt;571&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="207"&gt;Number of Logical Queries/logical SQL&lt;/td&gt;        &lt;td valign="top" width="59"&gt;3&lt;/td&gt;        &lt;td valign="top" width="133"&gt;1713&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;This number above – approximately 1700 – gives you a number of sizing guidelines. For example, if your database will gracefully handle only about 600 connections/queries at a time – then you know you need approximately 3 (1700/600) databases to handle this load correctly.&lt;/p&gt;  &lt;p&gt;Also, if you find – for example due to memory issues – that an OBIEE instance will only scale up to a connection pool of 200 – you know you will need a cluster of about 8 (1700/200) instances of OBIEE to handle this load. &lt;/p&gt;  &lt;p&gt;Of course, you can also play with the the numbers above to try and get the required connection pool size down. For example, if by creating better aggregates, you are able to get the dashboard running time from 5s to 1s, this can be 5x reduction in the number of required connections.&lt;/p&gt;  &lt;br clear="all" /&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/359699111496312090-6770471491613951012?l=navi-obiee.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/PWOS1NNUphlwSUDpOLFkTr2rPpU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/PWOS1NNUphlwSUDpOLFkTr2rPpU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/PWOS1NNUphlwSUDpOLFkTr2rPpU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/PWOS1NNUphlwSUDpOLFkTr2rPpU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/ELxJo/~4/EAm0ADTKU-Y" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://navi-obiee.blogspot.com/feeds/6770471491613951012/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://navi-obiee.blogspot.com/2010/12/connection-pooling-and-sizing-of.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/359699111496312090/posts/default/6770471491613951012?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/359699111496312090/posts/default/6770471491613951012?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/ELxJo/~3/EAm0ADTKU-Y/connection-pooling-and-sizing-of.html" title="Connection Pooling and Sizing of Connection Pools" /><author><name>Mash</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://navi-obiee.blogspot.com/2010/12/connection-pooling-and-sizing-of.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUIAQnw9fyp7ImA9Wx5RF0s.&quot;"><id>tag:blogger.com,1999:blog-359699111496312090.post-4131227642018559725</id><published>2010-08-25T13:19:00.001-07:00</published><updated>2010-08-25T13:19:03.267-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-08-25T13:19:03.267-07:00</app:edited><title>Cache Purging – Session Variables</title><content type="html">&lt;p&gt;There is another way to purge cache for selected tables that is based on a pull mechanism – not push – which is to use session variables to detect when data on the underlying database has changed.&lt;/p&gt;  &lt;p&gt;Here is the sequence of things one has to do:&lt;/p&gt;  &lt;p&gt;1) Create a ETL_TIMESTAMP table on your warehouse as follows :&lt;/p&gt;  &lt;p&gt;&lt;em&gt;create table ETL_TIMESTAMP      &lt;br /&gt;(       &lt;br /&gt;&amp;#160; ETL_TIMESTAMP TIMESTAMP(6)       &lt;br /&gt;);&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;2) At the end of every ETL run, run the following script to refresh this timestamp:&lt;/p&gt;  &lt;p&gt;&lt;em&gt;truncate table ETL_TIMESTAMP;&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;insert into ETL_TIMESTAMP select sysdate from dual;&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;3) Now create a session variable so that every new session gets the value of the ETL refresh timestamp when it starts – by using the following SQL:&lt;/p&gt;  &lt;p&gt;&lt;em&gt;select etl_timestamp from etl_timestamp&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_DFS_9e7YDuU/THV6q1gRgMI/AAAAAAAABHg/1cwt5n9y_pI/s1600-h/image3.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_DFS_9e7YDuU/THV6sjT-4GI/AAAAAAAABHk/aY_ptuak37k/image_thumb1.png?imgmax=800" width="554" height="343" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;4) Finally you want to make sure that cache entries are discarded when the value of this variable changes. We now have to ensure that this variable is referenced in the query. This can be done in a number of ways – one of which is to reference it in the logical table source (LTS).&lt;/p&gt;  &lt;p&gt;Modify &lt;strong&gt;&lt;u&gt;every&lt;/u&gt;&lt;/strong&gt; LTS (or at least the one for which cache purges are required) by modifying the ‘WHERE clause’:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_DFS_9e7YDuU/THV6s1tqAZI/AAAAAAAABHo/gx9Tz8urTYM/s1600-h/image9.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_DFS_9e7YDuU/THV6tjZHgjI/AAAAAAAABHs/B7jXYOvrTlM/image_thumb5.png?imgmax=800" width="553" height="479" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Now cache entries will be automatically purged everytime you run ETL.&lt;/p&gt;  &lt;h3&gt;Pros and Cons&lt;/h3&gt;  &lt;p&gt;Pros&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;The most important difference between this method and the others we discussed &lt;a href="http://navi-obiee.blogspot.com/2010/08/cache-purging-api-calls.html"&gt;here&lt;/a&gt; and &lt;a href="http://navi-obiee.blogspot.com/2010/08/cache-purgingevent-polling-tables.html"&gt;here&lt;/a&gt;, is that being a pull API, it is fairly resilient to changes in physical configuration. If you add or remove servers from a clustered environment, or have Dev. / UAT / QA / Production BI servers pointed to the same warehouse database, each of the caches will automatically refresh when they should. &lt;/li&gt;    &lt;li&gt;Since this is session level, there is no latency to a cache refresh. As soon as the new data appears on the database, all new sessions will see the new data. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Cons&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Configuration maybe hard, if every LTS is to be modified. &lt;/li&gt;    &lt;li&gt;Existing sessions might see some old cache hits. If you have long running sessions, then you may need to enhance this to use both a session variable and a repository variable to provide staleness guarantees. The latter is left as an exercise for the reader. &lt;/li&gt; &lt;/ol&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/359699111496312090-4131227642018559725?l=navi-obiee.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/m3kE55tQXaBWHalicM_ZWW38uiM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/m3kE55tQXaBWHalicM_ZWW38uiM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/m3kE55tQXaBWHalicM_ZWW38uiM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/m3kE55tQXaBWHalicM_ZWW38uiM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/ELxJo/~4/85n83iW3nnE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://navi-obiee.blogspot.com/feeds/4131227642018559725/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://navi-obiee.blogspot.com/2010/08/cache-purging-session-variables.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/359699111496312090/posts/default/4131227642018559725?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/359699111496312090/posts/default/4131227642018559725?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/ELxJo/~3/85n83iW3nnE/cache-purging-session-variables.html" title="Cache Purging – Session Variables" /><author><name>Mash</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/_DFS_9e7YDuU/THV6sjT-4GI/AAAAAAAABHk/aY_ptuak37k/s72-c/image_thumb1.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://navi-obiee.blogspot.com/2010/08/cache-purging-session-variables.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0MMRXw5eip7ImA9Wx5REUs.&quot;"><id>tag:blogger.com,1999:blog-359699111496312090.post-5631488672517209274</id><published>2010-08-18T14:04:00.001-07:00</published><updated>2010-08-18T14:04:44.222-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-08-18T14:04:44.222-07:00</app:edited><title>Cache Purging – API calls</title><content type="html">&lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;In the last &lt;a href="http://navi-obiee.blogspot.com/2010/08/cache-purgingevent-polling-tables.html"&gt;post&lt;/a&gt;, we saw that you can take control over your cache entries and purge them on a table by table basis. However, if you are like most BI departments, your tables do not have independent refresh frequencies. You probably run ETL once (twice? three time?) a day, and that ETL updates nearly every table in the warehouse. In this case, clearing call is simply issuing the following command via odbc to the BI server at the end of your ETL process.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;em&gt; Call SAPurgeAllCache()&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Of course, if you have more than one BI server (e.g. in a cluster) you would have to issue this more than once – once for each server.&amp;#160; There are also API calls for purging cache by database/table but are required less often. If you do need to use these APIs see &lt;a href="http://obiee101.blogspot.com/2008/03/obiee-manage-cache-part-1.html"&gt;this&lt;/a&gt; great post by John.&lt;/p&gt;  &lt;h3&gt;Pros and Cons&lt;/h3&gt;  &lt;p&gt;Pros&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;This is much simpler to implement than event polling especially in environments with more than 1 BI server. There is no need for a database table with the event polling table. No need for separate schemas for each BI server, and no communication between the ETL tools and metadata except a one-time (hopefully) handoff of a list of BI servers to your ETL developer.&lt;/li&gt;    &lt;li&gt;Since this is a call directly into the BI server, there is no latency whereas with event polling entries could stay in the cache for an extra 10 minutes (polling interval).&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Cons&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;This is a syncronous API. If a BI server happens to be down – for administration or due to unintended failure – it might never receive this call, and will serve stale data when it brought online later.&lt;/li&gt;    &lt;li&gt;It is hard to add/remove servers to the cluster without modifying ETL scripts. Moreover, if another BI server points to the same environment – say the QA environment – it will never have its cache purged.&lt;/li&gt; &lt;/ol&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/359699111496312090-5631488672517209274?l=navi-obiee.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/BdWmqxu7BWucju85xcyrsyEIaEU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/BdWmqxu7BWucju85xcyrsyEIaEU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/BdWmqxu7BWucju85xcyrsyEIaEU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/BdWmqxu7BWucju85xcyrsyEIaEU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/ELxJo/~4/cZsqszMaNDg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://navi-obiee.blogspot.com/feeds/5631488672517209274/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://navi-obiee.blogspot.com/2010/08/cache-purging-api-calls.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/359699111496312090/posts/default/5631488672517209274?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/359699111496312090/posts/default/5631488672517209274?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/ELxJo/~3/cZsqszMaNDg/cache-purging-api-calls.html" title="Cache Purging – API calls" /><author><name>Mash</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://navi-obiee.blogspot.com/2010/08/cache-purging-api-calls.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkYBQH4yfyp7ImA9Wx5SF04.&quot;"><id>tag:blogger.com,1999:blog-359699111496312090.post-1780160065504136966</id><published>2010-08-13T14:23:00.001-07:00</published><updated>2010-08-13T15:22:31.097-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-08-13T15:22:31.097-07:00</app:edited><title>Cache Purging–Event Polling Tables</title><content type="html">&lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;We saw in our last &lt;a href="http://navi-obiee.blogspot.com/2010/08/cache-purging.html"&gt;post&lt;/a&gt; that setting timeouts for physical tables is not enough to ensure correctness when data changes and that some mechanism is required to signal to the OBIEE cache that it should purge old entries.&lt;/p&gt;  &lt;p&gt;There are various ways in which this can be accomplished. In simple systems, one option would be to use the ‘Event Polling Table’&lt;/p&gt;  &lt;p&gt;The idea behind this table is simple – it serves as a message bus. You put the names of the tables for which the data has changed. The OBIEE server &lt;strong&gt;polls&lt;/strong&gt; this table for update &lt;strong&gt;events &lt;/strong&gt;and purges cache entries that reference those tables. It also removes those entries from the polling table – so avoid purging them at the next polling interval.&lt;/p&gt;  &lt;p&gt;Here is how one configures the event polling table.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; Create the polling table on the database. For Oracle, the create table statement is:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;create table UET (        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; UpdateType Integer not null,         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; UpdateTime date DEFAULT SYSDATE not null,         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; DBName char(40) null,         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CatalogName varchar(40) null,         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; SchemaName varchar(40) null,         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; TableName varchar(40) not null,         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Other varchar(80) DEFAULT NULL         &lt;br /&gt;);&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;strong&gt;Step 2: &lt;/strong&gt;Import this table into the rpd and set up the connection pool info. Remember that this will not have user session – so needs a well defined user anme and password (i.e. :USER will not work)&lt;/p&gt;    &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_DFS_9e7YDuU/TGW308W-VGI/AAAAAAAABHQ/jxhQU8zcPFU/s1600-h/image%5B8%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" class="wlDisabledImage" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_DFS_9e7YDuU/TGW31eH1jKI/AAAAAAAABHU/NNjQq7CotqA/image_thumb%5B4%5D.png?imgmax=800" width="380" height="324" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Step 3:&lt;/strong&gt; Declare this table to be the event polling table by going to Tools –&amp;gt; Utilities&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_DFS_9e7YDuU/TGW31kFoOSI/AAAAAAAABHY/E7sa1zu_oz4/s1600-h/image%5B11%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; margin: 0px; display: inline; border-top: 0px; border-right: 0px" class="wlDisabledImage" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_DFS_9e7YDuU/TGW312HhfRI/AAAAAAAABHc/kt7cjrDd8U4/image_thumb%5B5%5D.png?imgmax=800" width="244" height="169" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;and set the polling frequency – it is recommend that this be higher than 10 minutes. A smaller polling frequency reduces possibility of stale cache but will impact end-user throughput.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Step 4:&lt;/strong&gt; Add code to your ETL process so that when a table is updated, rows are inserted into the event polling table. Remember to use the DB, schema and table names as defined in the rpd, not as defined on the database.&lt;/p&gt;  &lt;h1&gt;&lt;/h1&gt;  &lt;h3&gt;Pros and Cons&lt;/h3&gt;  &lt;p&gt;Pros&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Event polling is a very reliable way to purge cache for only those tables that have been updated, and is fairly easy to implement.&lt;/li&gt;    &lt;li&gt;Because of high selectivity – can be used in environments which have a high refresh rate. In particular, if you a warehouse where some table update frequently – say every 10 minutes - you can use implement event polling to delete entries which reference only the latter batch.&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Cons&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;The entries in the event polling table reference db, schema, catalog and table names are as defined in the repository and not in the database. This means that this requires communication between the ETL and the metadata developers on a regular basis to keep this working correctly.&lt;/li&gt;    &lt;li&gt;The above is compounded by the fact that entries involving aliases are not driven by the name of the base table. If you have ten aliases (say) for you your calendar table – a row needs to be inserted in the event polling table for each of those 10!&lt;/li&gt;    &lt;li&gt;Since there are practical limitations on how often you can poll, this still allows stale cache hits for up to 10 minutes.&lt;/li&gt;    &lt;li&gt;In any environment which has more than 1 BI server querying a single database (e.g. in a clustered environment), this can not be implemented. In such an environment the first server to find a record for DATE_D will delete its cache entries for it – but also the row in the event polling table. This means that the other servers in the cluster will never purge their cache for that table, and will continue to server old data. Users will see different results for reports depending upon which server they are routed to.&lt;/li&gt; &lt;/ol&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/359699111496312090-1780160065504136966?l=navi-obiee.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/INjsrY4fRC85SMeHRrO4NgjGB2U/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/INjsrY4fRC85SMeHRrO4NgjGB2U/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/INjsrY4fRC85SMeHRrO4NgjGB2U/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/INjsrY4fRC85SMeHRrO4NgjGB2U/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/ELxJo/~4/NRYh6h7QZ8E" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://navi-obiee.blogspot.com/feeds/1780160065504136966/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://navi-obiee.blogspot.com/2010/08/cache-purgingevent-polling-tables.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/359699111496312090/posts/default/1780160065504136966?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/359699111496312090/posts/default/1780160065504136966?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/ELxJo/~3/NRYh6h7QZ8E/cache-purgingevent-polling-tables.html" title="Cache Purging–Event Polling Tables" /><author><name>Mash</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/_DFS_9e7YDuU/TGW31eH1jKI/AAAAAAAABHU/NNjQq7CotqA/s72-c/image_thumb%5B4%5D.png?imgmax=800" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://navi-obiee.blogspot.com/2010/08/cache-purgingevent-polling-tables.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0UGQXk7cCp7ImA9Wx5SFU0.&quot;"><id>tag:blogger.com,1999:blog-359699111496312090.post-2536387943086443251</id><published>2010-08-10T21:33:00.001-07:00</published><updated>2010-08-10T21:33:40.708-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-08-10T21:33:40.708-07:00</app:edited><title>Cache purging</title><content type="html">&lt;p&gt;One of the most powerful, and least effort, features provided by the OBIEE stack for improving throughput is caching. For reports that have been executed before, OBIEE will serve the results from the mid-tier instead of going back to re-query the database.&lt;/p&gt;  &lt;p&gt;This has two advantages – first, the query that hits cache returns faster since it avoids the round trip to the database, and second that by reducing the percent of queries that hit the database, it improves the response time for the queries that do hit the database.&lt;/p&gt;  &lt;p&gt;However, a query that does not query the database can not, by definition, know if the data has changed on the database. Hence an important part of the caching strategy is defining how to avoid getting stale data out of cache. In this post I will examine the various options and their relative merits.&lt;/p&gt;  &lt;h1&gt;&lt;/h1&gt;  &lt;h4&gt;Cache Persistence Time&lt;/h4&gt;  &lt;p&gt;Your initial reaction may be to say that since we run ETL only once every day (or whatever your frequency may be), it is okay set the cache to expire every 24 hours. OBIEE even provides an option to expire cache entries after a given time period:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_DFS_9e7YDuU/TGIoG8jFgOI/AAAAAAAABGw/31xOdjc1kVw/s1600-h/image2.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_DFS_9e7YDuU/TGIoHJRhscI/AAAAAAAABG0/VPJ_GrWwm60/image_thumb.png?imgmax=800" width="244" height="197" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Unfortunately, cache persistence time is measured from the time the cache entry was created and not when the data is refreshed. This means that even if you set this to your ETL refresh interval, you will still get some reports being answered out of (stale) cache although the underlying data has changed. For example, imagine the case when ETL starts every night at 1 am:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_DFS_9e7YDuU/TGIoHfop3lI/AAAAAAAABG4/jA_DRw_UF2g/s1600-h/image%5B3%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; margin: 0px; display: inline; border-top: 0px; border-right: 0px" class="wlDisabledImage" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_DFS_9e7YDuU/TGIoHr7QyTI/AAAAAAAABG8/70k5HoOWH1o/image_thumb%5B1%5D.png?imgmax=800" width="244" height="54" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;You might be tempted to set the cache persistence time and assume that will take care of your purging data after every ETL. Unfortunately, this does not work. To understand why consider a report run at 12:30 am.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_DFS_9e7YDuU/TGIoIALv5uI/AAAAAAAABHA/AuTlgwg_urY/s1600-h/image%5B6%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; margin: 0px; display: inline; border-top: 0px; border-right: 0px" class="wlDisabledImage" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_DFS_9e7YDuU/TGIoIdjjlOI/AAAAAAAABHE/s0APLV1HR6Q/image_thumb%5B2%5D.png?imgmax=800" width="244" height="78" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;and then again at 2:30 am just two hours later.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_DFS_9e7YDuU/TGIoIrGjtsI/AAAAAAAABHI/JV5AT-bovzM/s1600-h/image%5B9%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; margin: 0px; display: inline; border-top: 0px; border-right: 0px" class="wlDisabledImage" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_DFS_9e7YDuU/TGIoI2GOylI/AAAAAAAABHM/8686cAhXyvg/image_thumb%5B3%5D.png?imgmax=800" width="244" height="75" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;This will hit cache entry created at 12:30 am since less than 24 hours have passed. However, the data in the underlying tables has changed completely.&lt;/p&gt;  &lt;p&gt;So it is clear that one needs some way of signaling changes on the database to the OBIEE server so it can purge the obsolete cache entries. In subsequent posts, I will talk about the various options available to you – as well as their pros and cons.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/359699111496312090-2536387943086443251?l=navi-obiee.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/GWPnJ200y14cZvLNOPl8TrlJCCI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/GWPnJ200y14cZvLNOPl8TrlJCCI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/GWPnJ200y14cZvLNOPl8TrlJCCI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/GWPnJ200y14cZvLNOPl8TrlJCCI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/ELxJo/~4/5ET1iT2StGk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://navi-obiee.blogspot.com/feeds/2536387943086443251/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://navi-obiee.blogspot.com/2010/08/cache-purging.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/359699111496312090/posts/default/2536387943086443251?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/359699111496312090/posts/default/2536387943086443251?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/ELxJo/~3/5ET1iT2StGk/cache-purging.html" title="Cache purging" /><author><name>Mash</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/_DFS_9e7YDuU/TGIoHJRhscI/AAAAAAAABG0/VPJ_GrWwm60/s72-c/image_thumb.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://navi-obiee.blogspot.com/2010/08/cache-purging.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkIAQn4zfSp7ImA9WxFbFUk.&quot;"><id>tag:blogger.com,1999:blog-359699111496312090.post-3875408244080490836</id><published>2010-07-07T14:10:00.001-07:00</published><updated>2010-07-07T17:22:23.085-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-07T17:22:23.085-07:00</app:edited><title>Tuning Data Warehouse Models on Oracle - 2</title><content type="html">&lt;p&gt;In the last post we talked about how, in a fact table, even high selectivity – 10 % - does not lead to reduction of the blocks read.&lt;/p&gt;  &lt;p&gt;This means that if you keep 10 years of data in the fact table – and select just 1 year – the database is on an average going to have to scan the full table. This can – will – be bad for performance. What one would ideally like to do – is just scan a 10th of the data. To accomplish that one has to ensure that each year is stored on the minimum number of blocks. This co-location of related records can be accomplished in three distinct ways.&lt;/p&gt;  &lt;p&gt;There are three tools available for us to accomplish that:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Index Organized table &lt;/li&gt;    &lt;li&gt;Partitioning&amp;#160; &lt;/li&gt;    &lt;li&gt;Physical Reordering via CTAS &lt;/li&gt; &lt;/ol&gt;  &lt;h2&gt;&lt;/h2&gt;  &lt;h2&gt;Index Organized Table&lt;/h2&gt;  &lt;p&gt;The easiest way to keep the rows ordered is to tell Oracle to keep them that way – i.e. via an index organized table. The syntax is simple – you just have to create the table with an organization index clause:&lt;/p&gt;  &lt;p&gt;&lt;em&gt;create table sales (&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;…&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;) organization index;&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;The table data is stored with the primary key index instead of in its own blocks. If the primary key is prefixed with the columns you want to sort on – then records with a given value will appear together. For example,&lt;/p&gt;  &lt;p&gt;&lt;em&gt;create table sales (&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;…,&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;constraint PK_SALES primary key (year, sales_id)&lt;/p&gt;  &lt;p&gt;&lt;em&gt;) organization index;&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;will keep all records for a given year together.&lt;/p&gt;  &lt;p&gt;However, we do not recommend actually doing this for fact tables because in our experience this does not work well with bitmap indexes. &lt;/p&gt;  &lt;h2&gt;Partitioning&lt;/h2&gt;  &lt;p&gt;If the number of values in the field that you want to co-locate by is small, you can typically partition by that field – for example, you may do something resembling the following:&lt;/p&gt;  &lt;p&gt;&lt;em&gt;&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;create table sales (…)&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; partition by range (year)&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; partition p1 values less than (2005) tablespace u1,&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; partition p2 values less than (2006) tablespace u2,&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; partition p3 values less than (2007) tablespace u3,&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; partition p4 values less than (2008) tablespace u4,&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;&amp;#160;&amp;#160; partition p5 values less than (MAXVALUE) tablespace u5;&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;You would of course, have to maintain it as years were added. This is made much easier by the use of interval partitioning introduced in 11g.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;create table sales (…)&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; partition by range (year)&lt;/em&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;interval&amp;#160; (1)&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; partition p1 values less than (2005) tablespace u1;&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;This is great when the number of partitions is variable – i.e. as data for future comes in.&lt;/p&gt;  &lt;p&gt;The thing to watch out for is when the cardinality of the columns you are sorting on is high. For example, if you were sorting on date instead of years, then instead of 10 partitions could end up with 3650 partitions. &lt;/p&gt;  &lt;h2&gt;CTAS&lt;/h2&gt;  &lt;p&gt;The last way to keep rows of a certain value together is to to simply recreate the table using CTAS. For example,&lt;/p&gt;  &lt;p&gt;create table sales_ordered as select * from sales order by date;&lt;/p&gt;  &lt;p&gt;Note that this option, unlike the other two, does not provide any knowledge of the physical ordering to the optimizer. However, the benefits of co-locating the rows (as discussed in &lt;a href="http://navi-obiee.blogspot.com/2010/04/tuning-data-warehouse-models-on-oracle.html"&gt;http://navi-obiee.blogspot.com/2010/04/tuning-data-warehouse-models-on-oracle.html&lt;/a&gt;) will continue to be available.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;In a warehouse environment, we recommend that you always be aware of the physical order of data in your fact tables. If the cardinality of your most common filtering attribute is low, partitioning may be the best way to order the rows. If high, then CTAS with order by may be your only solution.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/359699111496312090-3875408244080490836?l=navi-obiee.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/V7V7Bi47iNGQ-682Xs4KrxirMVc/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/V7V7Bi47iNGQ-682Xs4KrxirMVc/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/V7V7Bi47iNGQ-682Xs4KrxirMVc/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/V7V7Bi47iNGQ-682Xs4KrxirMVc/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/ELxJo/~4/Pt57gBJh5OE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://navi-obiee.blogspot.com/feeds/3875408244080490836/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://navi-obiee.blogspot.com/2010/07/tuning-data-warehouse-models-on-oracle.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/359699111496312090/posts/default/3875408244080490836?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/359699111496312090/posts/default/3875408244080490836?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/ELxJo/~3/Pt57gBJh5OE/tuning-data-warehouse-models-on-oracle.html" title="Tuning Data Warehouse Models on Oracle - 2" /><author><name>Mash</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://navi-obiee.blogspot.com/2010/07/tuning-data-warehouse-models-on-oracle.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkEBRHg5cSp7ImA9WxFTEUk.&quot;"><id>tag:blogger.com,1999:blog-359699111496312090.post-5138222680772439353</id><published>2010-04-01T12:04:00.001-07:00</published><updated>2010-04-01T12:04:15.629-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-04-01T12:04:15.629-07:00</app:edited><title>Tuning Data Warehouse Models on Oracle</title><content type="html">&lt;p&gt;While not strictly related to OBIEE – I am currently working on a number of database optimization tasks, and will discuss a couple of ideas to be aware of when designing a warehouse schema for the oracle database.&lt;/p&gt;  &lt;p&gt;Let me start with a simple question:&lt;/p&gt;  &lt;p&gt;Assume you have a table of&amp;#160; 1000 blocks – with a column ‘Digit’ (that goes from 0-9 obviously). If the table is properly indexed on ‘Digit’ and you query all records where Digit=’0’ – how may data blocks will you have to read ?&lt;/p&gt;  &lt;p&gt;Simple applying the unitary method gives you :&lt;/p&gt;  &lt;p&gt;(1/10) * 1000 = 100 blocks.&lt;/p&gt;  &lt;p&gt;Unfortunately, it turns out that even though this might be a reasonable estimate for an OLTP application – this can be rather dramatically wrong for a fact table in a DSS environment.&lt;/p&gt;  &lt;p&gt;Why? Well, if you have designed your star schema correctly, you only have some surrogate keys, and some measures in the fact table (no large varchars). Assuming 5 (4 byte) surrogate keys, and 10 (8 byte) measures – your record length is&lt;/p&gt;  &lt;p&gt;5x4+8x10=100 bytes long&lt;/p&gt;  &lt;p&gt;Now – your block size may be 8K – and so the number of records that fit in a single block is 8K/100=80 records. &lt;/p&gt;  &lt;p&gt;By now you are wondering what this has to do with the original question. A lot as it turns out. Remember, all reads and write are for the block as a whole – and a block has to be read if *any* of its rows qualify the criteria. What is the probability that out of 80 records on a given block - none of them are a digit 0:&lt;/p&gt;  &lt;p&gt;P(No 0’s)= P(1st record Not 0) x P(2nd Record not 0)… P(80th record not 0)&lt;/p&gt;  &lt;p&gt;=(0.9) ^ 80&lt;/p&gt;  &lt;p&gt;=0.00022 &lt;/p&gt;  &lt;p&gt;Which means in such an environment, the number of blocks that you would expect to read is 1000 x (1-0.00022) = 999.8 blocks. A very different answer from the simplistic 100 we first got we first got. &lt;/p&gt;  &lt;p&gt;And this is not all - if you use table compression (which gives you – say 50% gain) – and a large blocksize (recommended with compression) you may have as many as:&lt;/p&gt;  &lt;p&gt;32K/ (100 bytes *50% compression ratio)=640 records per block.&lt;/p&gt;  &lt;p&gt;In the next post – I will talk about what this means in terms of optimizer behavior.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/359699111496312090-5138222680772439353?l=navi-obiee.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/MP9yevedxTOiXpSIZzqEk9VCmMU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/MP9yevedxTOiXpSIZzqEk9VCmMU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/MP9yevedxTOiXpSIZzqEk9VCmMU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/MP9yevedxTOiXpSIZzqEk9VCmMU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/ELxJo/~4/JsaC7k8mtHo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://navi-obiee.blogspot.com/feeds/5138222680772439353/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://navi-obiee.blogspot.com/2010/04/tuning-data-warehouse-models-on-oracle.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/359699111496312090/posts/default/5138222680772439353?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/359699111496312090/posts/default/5138222680772439353?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/ELxJo/~3/JsaC7k8mtHo/tuning-data-warehouse-models-on-oracle.html" title="Tuning Data Warehouse Models on Oracle" /><author><name>Mash</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://navi-obiee.blogspot.com/2010/04/tuning-data-warehouse-models-on-oracle.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A08DSXo8cSp7ImA9WxBTGU0.&quot;"><id>tag:blogger.com,1999:blog-359699111496312090.post-1180811705761752054</id><published>2009-12-15T12:44:00.001-08:00</published><updated>2009-12-15T12:44:38.479-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-12-15T12:44:38.479-08:00</app:edited><title>Query Generation in OBIEE server</title><content type="html">&lt;p&gt;OBIEE Server will sometimes generate queries that look like this:&lt;/p&gt;  &lt;p&gt;NVL(“Column1”,’q’)=NVL(“Column2”,’q’) and NVL(“Column1”,’z’) =NVL(“Column2”,’z’)&lt;/p&gt;  &lt;p&gt;which seems a bit redundant – both the conditions are the same except for the constant q and z…&lt;/p&gt;  &lt;p&gt;The reason both parts of this condition are required is to guard against “Column1” or “Column2” having the values ‘q’ or ‘z’ as legitimate values. Let us do a truth table:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Truth Table for &lt;strong&gt;NVL(“Column1”,’q’)=NVL(“Column2”,’q’)&lt;/strong&gt;&lt;/p&gt;  &lt;table border="0" cellspacing="0" cellpadding="2" width="400"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;NULL&lt;/td&gt;        &lt;td valign="top" width="66"&gt;q&lt;/td&gt;        &lt;td valign="top" width="66"&gt;z&lt;/td&gt;        &lt;td valign="top" width="66"&gt;foo&lt;/td&gt;        &lt;td valign="top" width="66"&gt;bar&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="66"&gt;NULL&lt;/td&gt;        &lt;td valign="top" width="66"&gt;True&lt;/td&gt;        &lt;td valign="top" width="66"&gt;True&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="66"&gt;q&lt;/td&gt;        &lt;td valign="top" width="66"&gt;True&lt;/td&gt;        &lt;td valign="top" width="66"&gt;True&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="66"&gt;z&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;True&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="66"&gt;foo&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;True&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="66"&gt;bar&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;True&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Note the values are true when Column1=’q’ and Column2 is NULL – or vice versa.&lt;/p&gt;  &lt;p&gt;Truth Table for &lt;strong&gt;NVL(“Column1”,’z’)=NVL(“Column2”,’z’)&lt;/strong&gt;&lt;/p&gt;  &lt;table border="0" cellspacing="0" cellpadding="2" width="400"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;NULL&lt;/td&gt;        &lt;td valign="top" width="66"&gt;q&lt;/td&gt;        &lt;td valign="top" width="66"&gt;z&lt;/td&gt;        &lt;td valign="top" width="66"&gt;foo&lt;/td&gt;        &lt;td valign="top" width="66"&gt;bar&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="66"&gt;NULL&lt;/td&gt;        &lt;td valign="top" width="66"&gt;True&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;True&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="66"&gt;q&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;True&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="66"&gt;z&lt;/td&gt;        &lt;td valign="top" width="66"&gt;True&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;True&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="66"&gt;foo&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;True&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="66"&gt;bar&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;True&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;This can be true if either column is ‘z’ and the other is NULL.&lt;/p&gt;  &lt;p&gt;However, if we and the two, we get:&lt;/p&gt;  &lt;p&gt;Truth Table for &lt;strong&gt;NVL(“Column1”,’q’)=NVL(“Column2”,’q’)&lt;/strong&gt; and &lt;strong&gt;NVL(“Column1”,’z’)=NVL(“Column2”,’z’)&lt;/strong&gt;&lt;/p&gt;  &lt;table border="0" cellspacing="0" cellpadding="2" width="400"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;NULL&lt;/td&gt;        &lt;td valign="top" width="66"&gt;q&lt;/td&gt;        &lt;td valign="top" width="66"&gt;z&lt;/td&gt;        &lt;td valign="top" width="66"&gt;foo&lt;/td&gt;        &lt;td valign="top" width="66"&gt;bar&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="66"&gt;NULL&lt;/td&gt;        &lt;td valign="top" width="66"&gt;True&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="66"&gt;q&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;True&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="66"&gt;z&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;True&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="66"&gt;foo&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;True&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="66"&gt;bar&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="66"&gt;True&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;which is equivalent to the much more readable:&lt;/p&gt;  &lt;p&gt;“Column1”=”Column2” or (“Column1” is null and “Column2” is null)&lt;/p&gt;  &lt;p&gt;In fact, the latter formulation is what OBIEE used to generate for these joins in previous versions.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/359699111496312090-1180811705761752054?l=navi-obiee.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/DSiSnAqKnHRE1bsq4tmC--TJPi0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/DSiSnAqKnHRE1bsq4tmC--TJPi0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/DSiSnAqKnHRE1bsq4tmC--TJPi0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/DSiSnAqKnHRE1bsq4tmC--TJPi0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/ELxJo/~4/Isp1vGlpnI8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://navi-obiee.blogspot.com/feeds/1180811705761752054/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://navi-obiee.blogspot.com/2009/12/query-generation-in-obiee-server.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/359699111496312090/posts/default/1180811705761752054?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/359699111496312090/posts/default/1180811705761752054?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/ELxJo/~3/Isp1vGlpnI8/query-generation-in-obiee-server.html" title="Query Generation in OBIEE server" /><author><name>Mash</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://navi-obiee.blogspot.com/2009/12/query-generation-in-obiee-server.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkQNRnk5fyp7ImA9WxNaEE8.&quot;"><id>tag:blogger.com,1999:blog-359699111496312090.post-5253491660608095913</id><published>2009-11-23T16:59:00.001-08:00</published><updated>2009-11-23T16:59:57.727-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-23T16:59:57.727-08:00</app:edited><title>IndexCol (Part 2)</title><content type="html">&lt;p&gt;The IndexCol feature of Oracle Business Intelligence is not limited to dimensions as discussed in the previous post, but extends to measures.&lt;/p&gt;  &lt;p&gt;Let us start with a hypothetical example – you are building a repository for Sales Analysis for a large auto maker. While the number of cars sold, and the revenue generated are interesting by themselves, the requirements include a number of derived measures – Average Selling Price of a car, Growth rate since last year, Effective tax rate for each car sold and so on…&lt;/p&gt;  &lt;p&gt;To make this more complicated, let us assume that this car manufactures has independent business units, run in Europe, Asia and U.S.A – with their own data marts. It is expected that all queries will be querying from one (and only one) of these data marts depending on the user logged on – but it is required that all BUs use similar definitions for the various metrics. &lt;/p&gt;  &lt;p&gt;One (painful) way to implement this within OBI-EE would be to setup separate subject areas for each BU – and grant access to employee within that BU – only access to their own subject area. However, you would end up duplicating all of the derived measures.&lt;/p&gt;  &lt;p&gt;A far more effective method of development is to map simple measures to the respective data marts – add a layer of IndexCols to do My Revenue – and then define derived metrics on that abstraction layer. For example,&lt;/p&gt;  &lt;p&gt;Simple Measures:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;America.Revenue= sum(USA_Datamart.Revenue) &lt;/li&gt;    &lt;li&gt;Europe.Revenue= sum(Europe_Datamart.Revenue) &lt;/li&gt;    &lt;li&gt;Asia.Revenue=sum(Asia_Datamart.Revenue) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;IndexCol Abstraction&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;MyRevenue = IndexCol(VALUEOF(NQ_SESSION.BU), America.Revenue, Europe.Revenue, Asia.Revenue) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Finally, we can build our hierarchy of derived measures based on this one column. Here are some examples:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;LastYearSales = Ago(MyRevenue, 1, YEAR) &lt;/li&gt;    &lt;li&gt;Yearly Growth = (MyRevenue- AGO(MyRevenue, 1, YEAR))/Ago(MyRevenue, 1, YEAR) &lt;/li&gt;    &lt;li&gt;SalesForRedCars = FILTER(MyRevenue USING Color=’Red’) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Note that these measure now only need be created once – and will work equally well regardless of which BU you are in.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/359699111496312090-5253491660608095913?l=navi-obiee.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/8Ak-zPRy_PgRGdL2HYf4LphP9FA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/8Ak-zPRy_PgRGdL2HYf4LphP9FA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/8Ak-zPRy_PgRGdL2HYf4LphP9FA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/8Ak-zPRy_PgRGdL2HYf4LphP9FA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/ELxJo/~4/Dh7AaemWNp4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://navi-obiee.blogspot.com/feeds/5253491660608095913/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://navi-obiee.blogspot.com/2009/11/indexcol-part-2.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/359699111496312090/posts/default/5253491660608095913?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/359699111496312090/posts/default/5253491660608095913?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/ELxJo/~3/Dh7AaemWNp4/indexcol-part-2.html" title="IndexCol (Part 2)" /><author><name>Mash</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://navi-obiee.blogspot.com/2009/11/indexcol-part-2.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkMBR3w7cSp7ImA9WxNbFUs.&quot;"><id>tag:blogger.com,1999:blog-359699111496312090.post-423330564968840321</id><published>2009-11-18T09:14:00.001-08:00</published><updated>2009-11-18T09:14:16.209-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-18T09:14:16.209-08:00</app:edited><title>IndexCol</title><content type="html">&lt;p&gt;One of the features I am using in my current project is IndexCol, which is a really powerful feature that can save lots of metadata work, and provide extraordinary flexibility to the content you provide users.&lt;/p&gt;  &lt;p&gt;The syntax for IndexCol is simply:&lt;/p&gt;  &lt;p&gt;IndexCol(&amp;lt;Constant&amp;gt;, &amp;lt;Expr0&amp;gt;, &amp;lt;Expr1&amp;gt;, &amp;lt;Expr2&amp;gt; …).&lt;/p&gt;  &lt;p&gt;The constant above can be a session variable – and usually will be. And that is where the power of this construct comes from.&lt;/p&gt;  &lt;p&gt;Functionally, IndexCol just picks the nth Column based on the value of the constant – and so is equivalent to a case statement:&lt;/p&gt;  &lt;p&gt;case &amp;lt;constant&amp;gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;when 0&amp;#160; then Expr0&lt;/p&gt; &lt;/blockquote&gt;  &lt;blockquote&gt;   &lt;p&gt;when 1 then Expr1&lt;/p&gt;    &lt;p&gt;when 2 then Expr2&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;end&lt;/p&gt;  &lt;p&gt;What makes this different from the case statement though, is that the BI server will evaluate the case at the time it receives the query – not when it executes it. This allows for significant gains in the actual queries that are executed. In the next few posts, I will try and cover the various cases in which this may be useful.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Employee Level Hierarchy&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;It is a common requirement to start out a report at the level of the user. For example, consider the hierarchy below:&lt;/p&gt;  &lt;p&gt;CEO&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;COO&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; VP1&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; VP2&lt;/p&gt;    &lt;p&gt;CFO&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; VP3&lt;/p&gt;    &lt;p&gt;CMO&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; VP4&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;which is stored as:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;table border="0" cellspacing="0" cellpadding="2" width="391"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td valign="top" width="99"&gt;Manager Level 0&lt;/td&gt;        &lt;td valign="top" width="101"&gt;Manager Level 1&lt;/td&gt;        &lt;td valign="top" width="110"&gt;Employee &lt;/td&gt;        &lt;td valign="top" width="79"&gt;Level of Employee&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="102"&gt;CEO&lt;/td&gt;        &lt;td valign="top" width="104"&gt;CEO&lt;/td&gt;        &lt;td valign="top" width="112"&gt;CEO&lt;/td&gt;        &lt;td valign="top" width="77"&gt;0&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="104"&gt;CEO&lt;/td&gt;        &lt;td valign="top" width="105"&gt;COO&lt;/td&gt;        &lt;td valign="top" width="112"&gt;COO&lt;/td&gt;        &lt;td valign="top" width="76"&gt;1&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="105"&gt;CEO&lt;/td&gt;        &lt;td valign="top" width="106"&gt;COO&lt;/td&gt;        &lt;td valign="top" width="112"&gt;VP1&lt;/td&gt;        &lt;td valign="top" width="75"&gt;2&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="105"&gt;CEO&lt;/td&gt;        &lt;td valign="top" width="107"&gt;COO&lt;/td&gt;        &lt;td valign="top" width="112"&gt;VP2&lt;/td&gt;        &lt;td valign="top" width="75"&gt;2&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="106"&gt;CEO&lt;/td&gt;        &lt;td valign="top" width="107"&gt;CFO&lt;/td&gt;        &lt;td valign="top" width="112"&gt;CFO&lt;/td&gt;        &lt;td valign="top" width="75"&gt;1&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="106"&gt;CEO&lt;/td&gt;        &lt;td valign="top" width="107"&gt;CFO&lt;/td&gt;        &lt;td valign="top" width="112"&gt;VP3&lt;/td&gt;        &lt;td valign="top" width="75"&gt;2&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="106"&gt;CEO&lt;/td&gt;        &lt;td valign="top" width="107"&gt;CMO&lt;/td&gt;        &lt;td valign="top" width="112"&gt;CMO&lt;/td&gt;        &lt;td valign="top" width="75"&gt;1&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="106"&gt;CEO&lt;/td&gt;        &lt;td valign="top" width="107"&gt;CMO&lt;/td&gt;        &lt;td valign="top" width="112"&gt;VP4&lt;/td&gt;        &lt;td valign="top" width="75"&gt;0&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;In the above table, when the CEO logs to on to see the revenue for all his reports – he wants to see the report:&lt;/p&gt;  &lt;p&gt;&lt;em&gt;Select ManagerLevel0, Sales from SubjectArea&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;However, when the COO logs on to see the same report – He would like to start out at his level – namely:&lt;/p&gt;  &lt;p&gt;&lt;em&gt;Select ManagerLevel1, Sales from SubjectArea&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;This is accomplished rather simply using IndexCol. One needs to create a derived column which represents the level of the user.&lt;/p&gt;  &lt;p&gt;&lt;/p&gt; &lt;a href="http://lh5.ggpht.com/_DFS_9e7YDuU/SwQrZlVqT3I/AAAAAAAAAos/AuQQW-Hqhoc/s1600-h/image%5B7%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_DFS_9e7YDuU/SwQrZyZSFWI/AAAAAAAAAow/_uS2UhhnqpA/image_thumb%5B3%5D.png?imgmax=800" width="301" height="387" /&gt;&lt;/a&gt;   &lt;p&gt;&lt;/p&gt;  &lt;p&gt;The report can then be written as:&lt;/p&gt;  &lt;p&gt;&lt;em&gt;Select MyLevel, Sales from SubjectArea&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;This will then automatically switch to the correct semantics depending on who logs on.&lt;/p&gt;  &lt;p&gt;Two things that are noteworthy:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Drills work correctly. When the CEO is logged on, and he drills from his MyLevel, he will be taken to Level1….&lt;/li&gt;    &lt;li&gt;Aggregate Navigation works correctly. i.e., if you have an aggregate at ManagerLevel1, this report will hit the aggregate where possible.&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Both of the above would not have been possible if one uses the case statement equivalent.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/359699111496312090-423330564968840321?l=navi-obiee.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/JEKUlSOR1JKsApUrw-6L34cOGhE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/JEKUlSOR1JKsApUrw-6L34cOGhE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/JEKUlSOR1JKsApUrw-6L34cOGhE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/JEKUlSOR1JKsApUrw-6L34cOGhE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/ELxJo/~4/h9RoR9K9l28" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://navi-obiee.blogspot.com/feeds/423330564968840321/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://navi-obiee.blogspot.com/2009/11/indexcol.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/359699111496312090/posts/default/423330564968840321?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/359699111496312090/posts/default/423330564968840321?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/ELxJo/~3/h9RoR9K9l28/indexcol.html" title="IndexCol" /><author><name>Mash</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/_DFS_9e7YDuU/SwQrZyZSFWI/AAAAAAAAAow/_uS2UhhnqpA/s72-c/image_thumb%5B3%5D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://navi-obiee.blogspot.com/2009/11/indexcol.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkEMQ34yfSp7ImA9WxNVGU8.&quot;"><id>tag:blogger.com,1999:blog-359699111496312090.post-6855629092882206072</id><published>2009-10-30T11:51:00.001-07:00</published><updated>2009-10-30T11:51:22.095-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-30T11:51:22.095-07:00</app:edited><title>Version Control</title><content type="html">&lt;p&gt;OBIEE – provides a strong multi-user environment that you should use if you are building repositories in large teams. It allows segmentation of the metadata into projects – which are divided up by areas of responsibility – and so can can make development more modular and pleasant.&lt;/p&gt;  &lt;p&gt;Sometimes, though, you may not have a large repository and/or a team, and may want to use a version control system instead. You may want to do this for managing complex branching needs, or for continuous integration of the rpd with quality checks.&lt;/p&gt;  &lt;p&gt;In my current project, I am using TortoiseSVN, and I will demonstrate how to integrate rpd development into that control system, using admintool automation commands.&lt;/p&gt;  &lt;p&gt;To begin with you will need the following python scripts to be installed in a known location say c:\. They convert the file-based admintool automation commands to the corresponding command line versions.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Script 1 – compare.py&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;import os, sys, tempfile, subprocess, time   &lt;br /&gt;import msvcrt    &lt;br /&gt;msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) &lt;/p&gt;  &lt;p&gt;original=sys.argv[1]   &lt;br /&gt;modified=sys.argv[2] &lt;/p&gt;  &lt;p&gt;cmd=tempfile.mktemp()   &lt;br /&gt;f=file(cmd, 'w')    &lt;br /&gt;f.write(&amp;quot;Open &amp;quot;+original+&amp;quot; Administrator tc\n&amp;quot;)    &lt;br /&gt;f.write(&amp;quot;Compare &amp;quot;+modified+&amp;quot; Administrator tc\n&amp;quot;)    &lt;br /&gt;f.close() &lt;/p&gt;  &lt;p&gt;p=subprocess.Popen(r&amp;quot;c:\oraclebi\server\bin\admintool.exe -command &amp;quot;+cmd)&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;-------------------------------------------------------------&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Script 2 – merge.py&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;import os, sys, tempfile, subprocess, time   &lt;br /&gt;import msvcrt    &lt;br /&gt;msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) &lt;/p&gt;  &lt;p&gt;original=sys.argv[1]   &lt;br /&gt;modified=sys.argv[2]    &lt;br /&gt;current=sys.argv[3] &lt;/p&gt;  &lt;p&gt;dest=sys.argv[4]   &lt;br /&gt;cmd=tempfile.mktemp() &lt;/p&gt;  &lt;p&gt;print cmd   &lt;br /&gt;f=file(cmd, 'w')    &lt;br /&gt;f.write(&amp;quot;Open &amp;quot;+current+&amp;quot; Administrator tc\n&amp;quot;)    &lt;br /&gt;f.write(&amp;quot;Merge &amp;quot;+original+&amp;quot; &amp;quot;+modified+&amp;quot; Administrator tc Administrator tc\n&amp;quot;)    &lt;br /&gt;f.write(&amp;quot;SaveAs &amp;quot;+dest+&amp;quot;\n&amp;quot;)    &lt;br /&gt;f.close() &lt;/p&gt;  &lt;p&gt;p=subprocess.Popen(r&amp;quot;c:\oraclebi\server\bin\admintool.exe -command &amp;quot;+cmd)&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;while (True):   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; try:    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; time.sleep(10)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; f=open(dest,'rb')&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if f:    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; time.sleep(10)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; os._exit(0)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; except IOError:    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; time.sleep(5) &lt;/p&gt;  &lt;p&gt;print original, modified, current&lt;/p&gt;  &lt;p&gt;---------------------------------------------------------------&lt;/p&gt;  &lt;p&gt;Now all that remains is to tell your source control to use these scripts for compare and merge respectively. This is how I did this on Tortoise:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Go to the settings page and Click Diff Viewer:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_DFS_9e7YDuU/Sus1op4HwkI/AAAAAAAAAnU/HqKA6L0WdBg/s1600-h/image%5B5%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_DFS_9e7YDuU/Sus1o2PeGmI/AAAAAAAAAnY/PQu825lIReg/image_thumb%5B1%5D.png?imgmax=800" width="244" height="165" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Click the Advance button and then Add. In the Extention of mim-type box – enter &lt;em&gt;.rpd&lt;/em&gt;, and in the external program exnter the following:&lt;/p&gt;  &lt;p&gt;&amp;lt;Path_TO_PYTHON&amp;gt;/python.exe c:\compare.py&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_DFS_9e7YDuU/Sus1pK-MI0I/AAAAAAAAAnc/zZWd_tjqdWg/s1600-h/image%5B8%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_DFS_9e7YDuU/Sus1pU3_RrI/AAAAAAAAAng/T2ZlttfBwVE/image_thumb%5B2%5D.png?imgmax=800" width="244" height="89" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Similarly, go to the merge tool, and add the .rpd extension:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_DFS_9e7YDuU/Sus1pq4epPI/AAAAAAAAAnk/SJmoC9W0_ug/s1600-h/image%5B11%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_DFS_9e7YDuU/Sus1plFVzlI/AAAAAAAAAno/hWb1ZvZOecM/image_thumb%5B3%5D.png?imgmax=800" width="244" height="70" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Once you have configured this correctly, you will be able to use admintool to compare version straight from source control.&lt;/p&gt;  &lt;p&gt;For example:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_DFS_9e7YDuU/Sus1qLIoaXI/AAAAAAAAAns/b1dy8w_PjtA/s1600-h/image%5B14%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_DFS_9e7YDuU/Sus1qRbbbWI/AAAAAAAAAnw/6dzp2IQu3wQ/image_thumb%5B4%5D.png?imgmax=800" width="244" height="201" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;brings up admintool, with the comparison between the two repositories:&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/359699111496312090-6855629092882206072?l=navi-obiee.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/zG2rbyK9ys2uU21ZqwjWbss-1vo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/zG2rbyK9ys2uU21ZqwjWbss-1vo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/zG2rbyK9ys2uU21ZqwjWbss-1vo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/zG2rbyK9ys2uU21ZqwjWbss-1vo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/ELxJo/~4/pG0s3oxAVJQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://navi-obiee.blogspot.com/feeds/6855629092882206072/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://navi-obiee.blogspot.com/2009/10/version-control.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/359699111496312090/posts/default/6855629092882206072?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/359699111496312090/posts/default/6855629092882206072?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/ELxJo/~3/pG0s3oxAVJQ/version-control.html" title="Version Control" /><author><name>Mash</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh5.ggpht.com/_DFS_9e7YDuU/Sus1o2PeGmI/AAAAAAAAAnY/PQu825lIReg/s72-c/image_thumb%5B1%5D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://navi-obiee.blogspot.com/2009/10/version-control.html</feedburner:origLink></entry></feed>

