<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>RTFB.log</title>
	<atom:link href="http://rtfblog.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://rtfblog.com</link>
	<description>Read The F/*IXME*/ Blog!</description>
	<lastBuildDate>Tue, 07 Feb 2012 09:43:48 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='rtfblog.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>RTFB.log</title>
		<link>http://rtfblog.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://rtfblog.com/osd.xml" title="RTFB.log" />
	<atom:link rel='hub' href='http://rtfblog.com/?pushpress=hub'/>
		<item>
		<title>An overview of the Business Intelligence world</title>
		<link>http://rtfblog.com/2012/02/07/an-overview-of-the-business-intelligence-world/</link>
		<comments>http://rtfblog.com/2012/02/07/an-overview-of-the-business-intelligence-world/#comments</comments>
		<pubDate>Tue, 07 Feb 2012 09:30:44 +0000</pubDate>
		<dc:creator>Clément Perrod</dc:creator>
				<category><![CDATA[A few words about...]]></category>
		<category><![CDATA[bi]]></category>
		<category><![CDATA[data integration]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[elt]]></category>
		<category><![CDATA[etl]]></category>
		<category><![CDATA[ibm]]></category>
		<category><![CDATA[microsoft]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[reporting]]></category>
		<category><![CDATA[restitution]]></category>
		<category><![CDATA[sap]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[talend]]></category>

		<guid isPermaLink="false">http://rtfblog.com/?p=458</guid>
		<description><![CDATA[Business Intelligence (BI) is a field of computer-science the goal of which is to build decision support systems. According to Wikipedia, BI involves the means, the tools and the methods used to collect, consolidate and produce the data model, and to finally display it. It is designed: to help a company taking decisions; to cover [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rtfblog.com&amp;blog=18436446&amp;post=458&amp;subd=rtfblog&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Business Intelligence (<abbr title="Business Intelligence">BI</abbr>) is a field of computer-science the goal of which is to build <a href="http://en.wikipedia.org/wiki/Decision_support_system">decision support systems</a>.</p>
<p>According to Wikipedia, BI involves the means, the tools and the methods used to collect, consolidate and produce the data model, and to finally display it. It is designed:</p>
<ul>
<li>to help a company taking decisions;</li>
<li>to cover its whole activity for people in charge of the strategy.</li>
</ul>
<p>Simply put, BI is the art of transforming raw data into valuable information.</p>
<p>This article begins with an introduction to BI, then describes the main actors of the BI market, and what their products are designed for.</p>
<p><span id="more-458"></span></p>
<h3>Business Intelligence</h3>
<p>Setting up a BI solution means building a decision tool from internal and external data. The goal of BI is to provide the information required to take decisions. The main steps of any BI projects include:</p>
<ol>
<li><strong>Collecting</strong> data from all the existing sources and putting it into an <a href="http://en.wikipedia.org/wiki/Operational_data_store"><abbr title="Operational Data Store">ODS</abbr></a>. Data is simply extracted from <a href="http://en.wikipedia.org/wiki/RDBMS"><abbr title="Relational Database Management System">RDBMS</abbr></a>, <a href="http://en.wikipedia.org/wiki/Enterprise_resource_planning"><abbr title="Enterprise Resource Planning">ERP</abbr></a>, <a href="http://en.wikipedia.org/wiki/Customer_relationship_management"><abbr title="Customer Relationship Management">CRM</abbr></a> systems, flat files, structured files (XML, CSV, XLS…) and loaded into a <a href="http://en.wikipedia.org/wiki/Dbms"><abbr title="Database Management System">DBMS</abbr></a>.</li>
<li><strong>Consolidating</strong> data into the <a href="http://en.wikipedia.org/wiki/Data_warehouse"><abbr title="Data warehouse">DWH</abbr></a> and as many <a href="http://en.wikipedia.org/wiki/Data_mart"><abbr title="Data marts">DM</abbr></a> as needed (one or more by line of work, depending on the needs). Data is extracted from the ODS and loaded into the DWH and the DM after some transformations. One also uses <a href="http://en.wikipedia.org/wiki/OLAP_cube"><abbr title="Online analytical processing">OLAP</abbr> Cubes</a> for projects involving multi-dimensional data.</li>
<li><strong>Consuming</strong> data using front-ends such as web or mobile applications. These applications are built using specific tools and allow the user to display pre-computed dashboards or to explore the information stored in the DWH, the DM or the Cube.</li>
<li><strong>Analyzing</strong> data with data-mining tools.</li>
</ol>
<p><img src="http://rtfblog.files.wordpress.com/2012/01/bi-key-steps.png?w=600" alt="Key steps of BI: collect, consolidate, consume, analyze." /></p>
<p>BI uses three kinds of technologies (we won&#8217;t talk about data-mining):</p>
<ul>
<li>data integration tools (also known as <a href="http://en.wikipedia.org/wiki/Extract,_transform,_load"><abbr title="Extract Transform and Load">ETL</abbr></a> or <abbr title="Extract Load and Transform">ELT</abbr>) to collect and consolidate data;</li>
<li>databases to store data into the ODS, the DWH, the DM or the cubes;</li>
<li>reporting tools to create dashboard, scorecards and to let end-users explore the data.</li>
</ul>
<p>Each technology may be used independently and for different purposes.</p>
<p>The following figure describes the data lifecycle from the sources to the end-user.</p>
<p><img src="http://rtfblog.files.wordpress.com/2012/01/bi-steps.png?w=600" alt="Data lifecycle: integration, storage, presentation to the end-user." /></p>
<h3>Data Integration</h3>
<p>Data integration is performed using ETL or ELT tools.</p>
<p>An ETL extracts data from different sources, applies transformations (cleansing, renaming, computing) using its own engine (implemented in general-purpose programming languages, such as Java, C++…) and loads data into the target tables. <a href="http://www.informatica.com/us/products/enterprise-data-integration/powercenter/">Informatica PowerCenter</a>, <a href="http://www-01.ibm.com/software/data/infosphere/datastage/">IBM Datastage</a>, <a href="http://msdn.microsoft.com/en-us/library/ms141026.aspx">Microsoft SQL Server Integration Services</a>, <a href="http://www.sap.com/uk/solutions/sapbusinessobjects/large/business-intelligence/BI-platform/sap-businessobjects-integration/index.epx">SAP BO Integration</a> and <a href="http://www.talend.com/products/enterprise-di.php">Talend Enterprise Data Integration</a> are ETLs. </p>
<p>Unlike in an ETL, the transformation process in an ELT is performed using the target DMBS engine (SQL language), like <a href="http://www.oracle.com/technetwork/middleware/data-integrator/overview/index.html">Oracle Data Integrator</a>.</p>
<p>In both cases, data integration tools move data from many different sources to a single target that may contain many tables. To choose an ETL/ELT tool, a company may consider the cost of the tools, the possibility to load data from all of its sources&#8217; kinds, the language used (Java, SQL, Perl…), as well as the <a href="http://en.wikipedia.org/wiki/Integrated_development_environment"><abbr title="Integrated Development Environment">IDE</abbr></a> that comes with it.</p>
<h3>Databases</h3>
<p>Databases store the result of data integration. They need to be really efficient, especially for reading operations, because many end-users may use dashboards or data exploration at the same time and on a lot of data. In contrast, writing operations are often performed off the working hours.</p>
<p>The most popular databases are relational, like <a href="http://en.wikipedia.org/wiki/Microsoft_SQL_Server">Microsoft SQL Server</a>, <a href="http://en.wikipedia.org/wiki/IBM_DB2">IBM DB2</a>, <a href="http://en.wikipedia.org/wiki/Oracle_Database">Oracle RDBMS</a>, <a href="http://en.wikipedia.org/wiki/Mysql">MySQL</a> or <a href="http://en.wikipedia.org/wiki/Postgresql">PostgreSQL</a>. The choice between them is done depending on their price (some are free, some other are very expensive) but also by looking at the administration tools, the IDE and the SQL extensions provided by the editor. Although RDBMS are used, data modeling is typically done according to a <a href="http://en.wikipedia.org/wiki/Star_schema">star schema</a>, which does not fit into the normal form.</p>
<p><img src="http://rtfblog.files.wordpress.com/2012/01/bi-star-schema.png?w=600" alt="Example of a star schema." /></p>
<p><a href="http://en.wikipedia.org/wiki/Teradata#Technology_and_Products">Teradata Database</a> and <a href="http://en.wikipedia.org/wiki/Greenplum">Greenplum</a> are also RDBMS but they are specialized in big volumes and use massive parallel processing. For companies with big volumes, it&#8217;s almost mandatory to use such databases to keep good performances.</p>
<p>Finally, in order to optimize reading operations, some databases like <a href="http://en.wikipedia.org/wiki/Sybase_IQ">SAP Sybase IQ</a> are column-oriented (as opposed to RDBMS that are row-oriented).</p>
<h3>Reporting</h3>
<p>Last but not least, the reporting tools are very important because they are the only mean by which end-users will interact with the information. The reporting market is more complex because there is a large number of editors that are very different from each other. But at the end, the way they work is very similar:</p>
<ol>
<li>Developers must specify the way the tool accesses data: connection to the database, data modeling (using star schema, dimensions and fact tables).</li>
<li>Then end-users explore data themselves or / and use pre-computed dashboards.</li>
</ul>
<p>The leaders in this market are (more because of acquisitions and the editors&#8217; reputation than on the basis of some quality criteria):</p>
<ul>
<li><a href="http://www-01.ibm.com/software/analytics/cognos/">IBM Cognos</a></li>
<li><a href="http://www.oracle.com/us/solutions/ent-performance-bi/enterprise-edition-066546.html">Oracle BI Enterprise Edition</a></li>
<li><a href="http://www.sap.com/solutions/sapbusinessobjects/large/business-intelligence/index.epx">SAP Business Object</a></li>
<li><a href="http://msdn.microsoft.com/en-us/library/ms159106.aspx">Microsoft SQL Server Restitution Services</a></li>
<p>Some challengers are also very competitive and gaining market share, like <a href="http://www.qlikview.com/en">Qlikview</a> (first to make in-memory systems popular), <a href="http://www.microstrategy.com/">Microstrategy</a> (one of the best mobile applications as of today), <a href="http://www.tableausoftware.com/">Tableau Software</a> (massively used in the USA), <a href="http://bimeanalytics.com/?lang=en">Bime</a> and <a href="http://www.bittle-solutions.com/en">Bittle</a> (BI in <a href="http://en.wikipedia.org/wiki/Software_as_a_service"><abbr title="Software as as Service">SaaS</abbr></a>).</p>
<p>Again, the choice of a reporting tool depends on its price, but also its speed and the ease of access for end-users. Each company has its own needs and constraints.</p>
<h3>Full BI Suites</h3>
<p>Some editors provide a data integrator, a database, and a reporting tool: so they have a full BI suite. It is the reason why IBM has bought Cognos and Datastage, Oracle has bought Sybase, Hyperion and Sunopsis, and SAP has bought Business Object. Microsoft has had a different strategy and has built its own suite by developing a data integration and a reporting tool on top of Microsoft SQL Server, but the result is the same: a BI suite.</p>
<p>Besides the big ones, there are three BI suites that deserve to be introduced because they are open-source and less expensive, and offer a real alternative to IBM, Oracle or SAP (although Microsoft BI is cheaper):</p>
<ul>
<li><a href="http://www.pentaho.com/">Pentaho</a></li>
<li><a href="http://www.jaspersoft.com/">Jaspersoft</a> (using Talend as data integration tool)</li>
<li><a href="http://www.spagoworld.org">SpagoBI</a></li>
</ul>
<h3>Challenges</h3>
<p>This article has introduced the market of BI as of today.<br />
But since it is an active market, new concepts are now emerging:</p>
<ul>
<li><strong>Mobility</strong>. People are now working everywhere: at home, at work, in public transports, and the use of tablets, mobile phones or notebooks is very common in meetings. BI reports must evolve and the dashboards&#8217; layouts have to be compatible with mobiles and tablets.</li>
<li><strong>Data Quality</strong> / <a href="http://en.wikipedia.org/wiki/Master_Data_Management"><abbr title="Master Data Management">MDM</abbr></a>.</li>
<li><strong>In-memory applications</strong>. Computers are built with increasing RAM capacity. Accessing data from RAM is much more efficient than from disk. In-memory applications use powerful and specific algorithms to compress and access data. A growing number of big editors are selling <a href="http://en.wikipedia.org/wiki/Computer_appliance">appliances</a> to support the in-memory concept: <a href="http://www.sap.com/hana/index.epx">Hana</a> by SAP, <a href="http://www.oracle.com/us/solutions/ent-performance-bi/business-intelligence/exalytics-bi-machine/overview/index.html">Exalytics</a> by Oracle.</li>
<li><strong>Semi-structured and unstructured data</strong>. Most of the time, the company&#8217;s knowledge is stored as unstructured data, like e-mails, and it is very difficult to analyze it. This is what <a href="http://rtfblog.com/2011/04/11/introduction-sba/"><abbr title="Search Based Applications">SBA</abbr></a> are trying to deal with.</li>
<li><strong>Big data</strong>. Companies like Facebook, Google or Yahoo have to deal with increasingly large volumes of data. To be able to store, analyze or even access everything rapidly, they have developed new technologies around clusters, parallel architectures and distributed computing, with solutions like the <a href="http://en.wikipedia.org/wiki/MapReduce">MapReduce</a> framework used by <a href="http://hadoop.apache.org/">Apache Hadoop</a> (among others), or new database concepts such as <a href="http://en.wikipedia.org/wiki/NoSQL">NoSQL</a> (because RDBMS do not meet their needs). This challenge is often called “big data” and might be the biggest of 2012, but we will talk about it in another article.</li>
</ul>
<h3>Going further</h3>
<li><a href="http://en.wikipedia.org/wiki/Business_intelligence"> Business intelligence (EN)</a></li>
<li><a href="http://www.youtube.com/watch?v=_1y5jBESLPE&amp;feature=player_embedded"> Video: History of Business Intelligence (EN)</a></li>
<li><a href="http://www.bi-verdict.com/fileadmin/FreeAnalyses/Comment_InMemBI.htm"> What in-memory BI &#8216;revolution&#8217; (EN)</a></li>
<li><a href="http://elasticube.blogspot.com/2010/09/in-memory-bi-is-not-future-its-past.html"> In-memory BI is not the future. It’s the past. (EN)</a></li>
<li><a href="http://tdwi.org/articles/2011/12/28/mobile-business-intelligence-and-analytics-executive-summary.aspx"> Mobile Business Intelligence and Analytics (EN)</a></li>
<li><a href="http://tdwi.org/articles/2011/12/13/data-management-2011.aspx"> Data Management: The Year Past, The Year Ahead (EN)</a></li>
<li><a href="http://tdwi.org/Articles/2012/01/10/BI-Future-has-Already-Happened.aspx"> BI 2012: The Future that has Already Happened (EN)</a></li>
<li><a href="http://www.databasejournal.com/sqletc/article.php/3905531/article.htm"> 10 things you Need to Know About NoSQL Databases (EN)</a></li>
<li><a href="http://blog.nahurst.com/visual-guide-to-nosql-systems"> Visual Guide to NoSQL Systems (EN)</a></li>
<li><a href="http://horicky.blogspot.com/2009/11/nosql-patterns.html"> NOSQL Patterns (EN)</a></li>
<li><a href="http://www.dbms2.com/2012/01/08/big-data-terminology-and-positioning"> Big data terminology and positioning (EN)</a></li>
<li><a href="http://tdwi.org/articles/2012/01/10/search-based-applications-set-to-thrive.aspx"> Why Search-Based Applications are Set to Thrive (EN)</a></li>
<h3>Credits</h3>
<ul>
<li>Illustration of the star schema by SqlPac under the Creative Commons Attribution-ShareAlike 3.0 License</li>
</ul>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rtfblog.wordpress.com/458/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rtfblog.wordpress.com/458/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/rtfblog.wordpress.com/458/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/rtfblog.wordpress.com/458/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/rtfblog.wordpress.com/458/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/rtfblog.wordpress.com/458/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/rtfblog.wordpress.com/458/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/rtfblog.wordpress.com/458/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/rtfblog.wordpress.com/458/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/rtfblog.wordpress.com/458/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/rtfblog.wordpress.com/458/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/rtfblog.wordpress.com/458/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/rtfblog.wordpress.com/458/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/rtfblog.wordpress.com/458/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rtfblog.com&amp;blog=18436446&amp;post=458&amp;subd=rtfblog&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://rtfblog.com/2012/02/07/an-overview-of-the-business-intelligence-world/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/145308e11029ad4a7849391d94d51b79?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">cperrod</media:title>
		</media:content>

		<media:content url="http://rtfblog.files.wordpress.com/2012/01/bi-key-steps.png" medium="image">
			<media:title type="html">Key steps of BI: collect, consolidate, consume, analyze.</media:title>
		</media:content>

		<media:content url="http://rtfblog.files.wordpress.com/2012/01/bi-steps.png" medium="image">
			<media:title type="html">Data lifecycle: integration, storage, presentation to the end-user.</media:title>
		</media:content>

		<media:content url="http://rtfblog.files.wordpress.com/2012/01/bi-star-schema.png" medium="image">
			<media:title type="html">Example of a star schema.</media:title>
		</media:content>
	</item>
		<item>
		<title>Update or insert rows in SQL</title>
		<link>http://rtfblog.com/2011/09/07/update-or-insert/</link>
		<comments>http://rtfblog.com/2011/09/07/update-or-insert/#comments</comments>
		<pubDate>Wed, 07 Sep 2011 19:55:36 +0000</pubDate>
		<dc:creator>Clément Perrod</dc:creator>
				<category><![CDATA[HowTo]]></category>
		<category><![CDATA[DBMS]]></category>
		<category><![CDATA[IBM DB2]]></category>
		<category><![CDATA[Insert]]></category>
		<category><![CDATA[MSSQL]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[Update]]></category>

		<guid isPermaLink="false">http://rtfblog.wordpress.com/?p=422</guid>
		<description><![CDATA[Some operations are not as easy in SQL as in procedural or imperative languages. For example while it is very intuitive to make an update or insert (also known as “upsert”) operation on a std::vector in C++, it is tricky in SQL. The upsert operation is: update data if already in the set and insert [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rtfblog.com&amp;blog=18436446&amp;post=422&amp;subd=rtfblog&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Some operations are not as easy in <a href="http://en.wikipedia.org/wiki/SQL"><abbr title="Simple Query Language">SQL</abbr></a> as in procedural or imperative languages. For example while it is very intuitive to make an update or insert (also known as “upsert”) operation on a <code>std::vector</code> in <a href="http://en.wikipedia.org/wiki/C%2B%2B">C++</a>, it is tricky in SQL. The upsert operation is: update data if already in the set and insert it otherwise.</p>
<p>As for <a href="/2011/06/27/recursion-in-sql/">recursion in SQL</a>, the way to perform an upsert depends on the <a href="http://en.wikipedia.org/wiki/Database_management_system"><abbr title="Database Management System">DBMS</abbr></a> and its version.</p>
<p><span id="more-422"></span></p>
<p>This article introduces different methods to upsert data in a table. Many solutions are introduced because not all DBMS are compatible with <a href="http://en.wikipedia.org/wiki/SQL:2008">SQL:2008</a> and the <code>MERGE</code> statement. As of today, it is compatible from these versions:</p>
<ul>
<li><a href="http://technet.microsoft.com/en-us/library/bb510625.aspx">Microsoft SQL Server 2008</a></li>
<li><a href="http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/index.jsp?topic=/com.ibm.db2.luw.sql.ref.doc/doc/r0010873.html">IBM DB2 v9</a></li>
<li><a href="http://download.oracle.com/docs/cd/E11882_01/server.112/e17118/statements_9016.htm#SQLRF01606">Oracle 9i</a></li>
</ul>
<p>MySQL does not provide this statement but its own SQL extentions:</p>
<ul>
<li><a href="http://dev.mysql.com/doc/refman/5.0/en/replace.html"><CODE>REPLACE</code> statement</a></li>
<li><a href="http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html"><code>ON DUPLICATE KEY</code> clause for <code>INSERT</code> statement</a>
</li>
</ul>
<p>Microsoft SQL Server 2000 and 2005 don't provide this feature but upsert is possible using the <a href="http://msdn.microsoft.com/en-us/library/ms177564.aspx"><code>output</code> clause for the <code>UPDATE</code> statement</a>.</p>
<p>Finally, the only solution I am aware of for PostgreSQL is to use a cursor and test each line: rows existing in the target table are updated and the others are inserted.</p>
<p style="font-style:italic;">Beware: all examples were written under Microsoft SQL Server 2008 (except the MySQL part). They may use some specific code but should remain fully understandable by everyone used to SQL.</p>
<h2>Dataset</h2>
<p>Before introducing all methods, let's set up the sample data.</p>
<p><code>@tUsers</code> is the working table. It contains a list of users with one particular field: <code>active</code>. When inserting data, this field is not set.</p>
<p><pre class="brush: sql;">
declare	@tUsers		table
(
	id		int		NOT NULL,
	firstName	varchar (30)	NOT NULL,
	lastName	varchar (30)	NOT NULL,
	active		tinyint		NULL
)

insert into @tUsers	(id, firstname,	lastname)
values	(1, 'Clément', 'Perrod')

insert into @tUsers	(id, firstname,	lastname)
values	(2, 'Thomas', 'Dupont')

insert into @tUsers	(id, firstname,	lastname)
values	(3, 'John', 'Doe')
</pre></p>
<p>The table contains the following rows:</p>
<pre>
id	firstName	lastName	active
1	Clément	        Perrod	        NULL
2	Thomas	        Dupont	        NULL
3	John	        Doe	        NULL
</pre>
<p><code>@tStaging</code> will be the source table for upsert in <code>@tUsers</code>. Some rows are new and others are just an update for the <code>active</code> field.
</p>
<p><pre class="brush: sql;">
declare	@tStaging	table
(
	id		int		NOT NULL,
	firstName	varchar (30)	NOT NULL,
	lastName	varchar (30)	NOT NULL,
	active		tinyint		NULL
)

insert into @tStaging	(id, firstname,	lastname, active)
values	(1, 'Clément', 'Perrod', 1)

insert into @tStaging	(id, firstname,	lastname, active)
values	(3, 'John', 'Doe', 0)

insert into @tStaging	(id, firstname,	lastname)
values	(4, 'Elise', 'Duffin')

insert into @tStaging	(id, firstname,	lastname)
values	(5, 'Anonie', 'Mousse')
</pre></p>
<p>The table contains following rows:</p>
<pre>
id	firstName	lastName	active
1	Clément		Perrod		1
3	John		Doe		0
4	Elise		Duffin		NULL
5	Anonie		Mousse		NULL
</pre>
<h2>Methods</h2>
<h3><code>MERGE</code> statement</h3>
<p>The easiest way to perform upsert is to use the <code>MERGE</code> statement introduced by SQL:2008. Its syntax is pretty intuitive: different treatments are applied on the target table using data from the source table depending on a merging clause. In this article it is used for upsert, but it is also possible to use it to delete data in target table.</p>
<p><pre class="brush: sql;">
MERGE 
    [ TOP ( expression ) [ PERCENT ] ] 
    [ INTO ] &lt;target_table&gt; [ WITH ( &lt;merge_hint&gt; ) ] [ [ AS ] table_alias ]
    USING &lt;table_source&gt; 
    ON &lt;merge_search_condition&gt;
    [ WHEN MATCHED [ AND &lt;clause_search_condition&gt; ]
        THEN &lt;merge_matched&gt; ] [ ...n ]
    [ WHEN NOT MATCHED [ BY TARGET ] [ AND &lt;clause_search_condition&gt; ]
        THEN &lt;merge_not_matched&gt; ]
    [ WHEN NOT MATCHED BY SOURCE [ AND &lt;clause_search_condition&gt; ]
        THEN &lt;merge_matched&gt; ] [ ...n ]
    [ &lt;output_clause&gt; ]
    [ OPTION ( &lt;query_hint&gt; [ ,...n ] ) ]    
;
</pre></p>
<p>The upsert is as easy as this:</p>
<p><pre class="brush: sql;">
merge	@tUsers		as us
using	@tStaging	as st
on	us.id = st.id
/*	Update	*/
when matched then
	update
	set		us.active = st.active
/*	Insert	*/
when not matched then
	insert (id, firstName, lastName, active)
	values (st.id, st.firstName, st.lastName, st.active)
/*	Mandatory semi colonn	*/
;
</pre></p>
<h3><code>ON DUPLICATE KEY</code> clause of the <code>INSERT</code> statement</h3>
<p>This upsert method is based on the <code>ON DUPLICATE KEY</code> clause for the <code>INSERT</code> statement, which is available in <a href="http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html">MySQL 5</a> and above.</p>
<p>This solution only works if the table @tUsers has a primary key. Thus, for this example to work, the table declaration is:</p>
<p><pre class="brush: sql;">
CREATE TABLE `tUsers` (
  `id` int(11) NOT NULL,
  `firstName` varchar(30) NOT NULL,
  `lastName` varchar(30) NOT NULL,
  `active` tinyint(4) DEFAULT NULL,
  PRIMARY KEY (`id`,`firstName`,`lastName`)
)
;
INSERT INTO tUsers	(id, firstname,	lastname)
VALUES	(1, 'Clément', 'Perrod')
;
INSERT INTO tUsers	(id, firstname,	lastname)
VALUES	(2, 'Thomas', 'Dupont')
;
INSERT INTO tUsers	(id, firstname,	lastname)
VALUES	(3, 'John', 'Doe')

CREATE TABLE `tStaging` (
  `id` int(11) NOT NULL,
  `firstName` varchar(30) NOT NULL,
  `lastName` varchar(30) NOT NULL,
  `active` tinyint(4) DEFAULT NULL
  )
;
INSERT INTO tStaging	(id, firstname,	lastname, active)
VALUES	(1, 'Clément', 'Perrod', 1)
;
INSERT INTO tStaging	(id, firstname,	lastname, active)
VALUES	(3, 'John', 'Doe', 0)
;
INSERT INTO tStaging	(id, firstname,	lastname)
VALUES	(4, 'Elise', 'Duffin')
;
INSERT INTO tStaging	(id, firstname,	lastname)
VALUES	(5, 'Anonie', 'Mousse')
</pre></p>
<p>Using the clause is as simple as follows: </p>
<p><pre class="brush: sql;">
insert into	
	tUsers
select	st.id,
	st.firstName,
	st.lastName,
	st.active
from	tStaging	st
ON DUPLICATE KEY 
UPDATE	active = st.active
</pre></p>
<h3><code>OUTPUT</code> clause of the <code>UPDATE</code> statement</h3>
<p>This upsert method is based on the <code>OUTPUT</code> clause of the <code>UPDATE</code> statement, which is available in <a href="http://msdn.microsoft.com/en-us/library/ms177564.aspx">Microsoft SQL Server 2000 and 2005</a> and above.</p>
<p>First, an update is performed on <code>@tUsers</code>, using the rows of <code>@tStaging</code>. The <code>OUTPUT</code> clause keeps all updated rows in the <code>@tUpdated</code> table. We are now able to see which rows of <code>@tStaging</code> have been used and which have to be inserted.</p>
<p><pre class="brush: sql;">
declare	@tUpdated	table
(
	id		int
)

update	@tUsers
set	active = st.active
output	inserted.id
into	@tUpdated
from	@tStaging	st,
	@tUsers		us
where	us.id = st.id
</pre></p>
<p>The second step is a simple <code>INSERT</code> statement, in which rows that are not in <code>@tUpdated</code> are selected from <code>@tStaging</code> using a <code>LEFT OUTER JOIN</code> (or a <code>NOT EXISTS</code> statement).</p>
<p><pre class="brush: sql;">
insert into	
	@tUsers
select	st.id,
	st.firstName,
	st.lastName,
	st.active
from	@tStaging	st
left join
	@tUpdated	up
on	up.id = st.id
WHERE	up.id is null
</pre></p>
<h2>Final points</h2>
<p>In this article, I have been through the most famous solutions to update or insert rows in a table (except the cursor one). Even if some methods are easier to use, it all depends on the installed DBMS.</p>
<table>
<thead>
<tr>
<td><code> MERGE</code> statement</td>
<td><code>ON DUPLICATE KEY</code> clause for <code>INSERT</code> statement</td>
<td><code>output</code> clause for <code>UPDATE</code> statement</td>
<td>cursors</td>
</tr>
</thead>
<tbody>
<td>
<ul>
<li>IBM DB2</li>
<li>Microsoft SQL Server 2008</li>
<li>Oracle 9i and later versions</li>
</ul>
</td>
<td>
<ul>
<li>Microsoft SQL Server 2000</li>
<li>Microsoft SQL Server 2005</li>
</ul>
</td>
<td>
<ul>
<li>MySQL 5.5 and later version</li>
</ul>
</td>
<td>
<ul>
<li>PostgreSQL</li>
</ul>
</td>
</tbody>
</tr>
</table>
<p>Stay tuned: we will discuss later why there are so many differences between DBMS.</p>
<h2>Read more about merge</h2>
<ul>
<li><a href="http://technet.microsoft.com/en-us/library/bb510625.aspx">MS SQL Server 2008: MERGE</A></li>
<li><a href="http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/index.jsp?topic=/com.ibm.db2.luw.sql.ref.doc/doc/r0010873.html">IBM DB2 v9: MERGE</A></li>
<li><a href="http://download.oracle.com/docs/cd/E11882_01/server.112/e17118/statements_9016.htm#SQLRF01606">Oracle 11g: MERGE</A></li>
<li><a href="http://msdn.microsoft.com/en-us/library/ms177564.aspx">MS SQL Server 2000 and 2005: output<br />
clause</A></li>
<li><a href="http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html">MySQL 5: ON DUPLICATE KEY clause</A></li>
</ul>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rtfblog.wordpress.com/422/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rtfblog.wordpress.com/422/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/rtfblog.wordpress.com/422/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/rtfblog.wordpress.com/422/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/rtfblog.wordpress.com/422/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/rtfblog.wordpress.com/422/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/rtfblog.wordpress.com/422/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/rtfblog.wordpress.com/422/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/rtfblog.wordpress.com/422/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/rtfblog.wordpress.com/422/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/rtfblog.wordpress.com/422/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/rtfblog.wordpress.com/422/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/rtfblog.wordpress.com/422/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/rtfblog.wordpress.com/422/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rtfblog.com&amp;blog=18436446&amp;post=422&amp;subd=rtfblog&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://rtfblog.com/2011/09/07/update-or-insert/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/145308e11029ad4a7849391d94d51b79?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">cperrod</media:title>
		</media:content>
	</item>
		<item>
		<title>Fix Gallery3 to extract IPTC headlines and captions</title>
		<link>http://rtfblog.com/2011/07/27/fix-gallery3-to-extract-iptc-headlines-and-captions/</link>
		<comments>http://rtfblog.com/2011/07/27/fix-gallery3-to-extract-iptc-headlines-and-captions/#comments</comments>
		<pubDate>Wed, 27 Jul 2011 19:17:20 +0000</pubDate>
		<dc:creator>Albin Kauffmann</dc:creator>
				<category><![CDATA[HowTo]]></category>
		<category><![CDATA[IPTC]]></category>
		<category><![CDATA[photo]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://rtfblog.wordpress.com/?p=405</guid>
		<description><![CDATA[Gallery3, a web based photo album organizer, can extract the IPTC.Caption field of photos you import. This caption is then used to set the description of photos. However, this default behavior might not be what you would expect. Introduction to Gallery and IPTC Gallery is an open source web based photo album organizer. Gallery3 intends [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rtfblog.com&amp;blog=18436446&amp;post=405&amp;subd=rtfblog&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Gallery3, a web based photo album organizer, can extract the <code>IPTC.Caption</code> field of photos you import. This caption is then used to set the description of photos. However, this default behavior might not be what you would expect.<span id="more-405"></span></p>
<h2>Introduction to Gallery and IPTC</h2>
<p>Gallery is an open source web based photo album organizer. Gallery3 intends to replace the famous Gallery2. At the day of this writing, Gallery 3.0.2 is the latest release. Please find more information on the <a title="Website of Gallery3" href="http://gallery.menalto.com">website</a>.</p>
<p>The <abbr title="International Press Telecommunications Council">IPTC</abbr> <abbr title="Information Interchange Model">IIM</abbr> is a standard defining a set of metadata directly saved in photo files and thus allowing the portability of photo information and the compatibility between photo software. More information on IPTC can be found in the resources.</p>
<h2>Change Gallery&#8217;s default behavior</h2>
<p>The current stable release (Gallery 3.0.2) only extracts the <code>IPTC.Caption</code> field of photos you import. However, the world is imperfect and photo software are not using the same IPTC fields to designate the title and the description of a photo. As far as I know, metadata fields should match:</p>
<p><pre class="brush: plain; light: true;">
IPTC.Headline or IPTC.ObjectName =&gt; Title
IPTC.Caption or IPTC.Comment =&gt; Description
</pre></p>
<p>As I share my Gallery3 space with other users (who are potentially using different software) and that we usually set only a title to pictures, I&#8217;d like Gallery to automatically find and set the photos titles. In other words:</p>
<p><pre class="brush: plain; light: true;">
if IPTC.Headline or IPTC.ObjectName is set
   photo.title = (IPTC.Headline or IPTC.ObjectName)
   if IPTC.Caption or IPTC.Comment is set
     photo.description = (IPTC.Caption or IPTC.Comment)
else if IPTC.Caption or IPTC.Comment is set
   photo.title = (IPTC.Caption or IPTC.Comment)
</pre></p>
<p>You&#8217;ll find my patch <a title="Gallery3 patch on GitHub" href="https://gist.github.com/1041284">here</a>. Enjoy it! I did not send this code to the official project because developers don&#8217;t seem to agree on IPTC tags use (see the tickets in resources).</p>
<h2>Resources</h2>
<ul>
<li><a title="Gallery3 patch on GitHub" href="https://gist.github.com/1041284">My patch</a></li>
<li>trac tickets concerning this subject:
<ul>
<li><a href="http://sourceforge.net/apps/trac/gallery/ticket/608">Ticket 608</a></li>
<li><a href="http://sourceforge.net/apps/trac/gallery/ticket/499">Ticket 499</a></li>
</ul>
</li>
<li>IPTC norm:
<ul>
<li><a href="http://www.iptc.org/std/photometadata/specification/IPTC-PhotoMetadata-201007_1.pdf">IPTC standard for Photo Metadata</a></li>
<li><a href="http://www.itagsoftware.com/compatibility.php">Metadata, formats and applications compatibility</a></li>
</ul>
</li>
</ul>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rtfblog.wordpress.com/405/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rtfblog.wordpress.com/405/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/rtfblog.wordpress.com/405/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/rtfblog.wordpress.com/405/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/rtfblog.wordpress.com/405/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/rtfblog.wordpress.com/405/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/rtfblog.wordpress.com/405/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/rtfblog.wordpress.com/405/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/rtfblog.wordpress.com/405/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/rtfblog.wordpress.com/405/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/rtfblog.wordpress.com/405/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/rtfblog.wordpress.com/405/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/rtfblog.wordpress.com/405/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/rtfblog.wordpress.com/405/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rtfblog.com&amp;blog=18436446&amp;post=405&amp;subd=rtfblog&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://rtfblog.com/2011/07/27/fix-gallery3-to-extract-iptc-headlines-and-captions/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/a628b653fd3e853835a1ff16248d65af?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">albinkauffmann</media:title>
		</media:content>
	</item>
		<item>
		<title>Recursion in SQL</title>
		<link>http://rtfblog.com/2011/06/27/recursion-in-sql/</link>
		<comments>http://rtfblog.com/2011/06/27/recursion-in-sql/#comments</comments>
		<pubDate>Mon, 27 Jun 2011 20:56:51 +0000</pubDate>
		<dc:creator>Clément Perrod</dc:creator>
				<category><![CDATA[HowTo]]></category>
		<category><![CDATA[CTE]]></category>
		<category><![CDATA[IBM DB2]]></category>
		<category><![CDATA[MSSQL]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[recursion]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://rtfblog.wordpress.com/?p=369</guid>
		<description><![CDATA[We are used to easily writing recursive calls and loops in procedural languages, but this doesn&#8217;t hold true in SQL. Indeed, it depends on the DBMS used. This article will focus on the ability to write recursive queries using Common Table Expressions (CTE). CTE are an addition from the SQL 1999 standard and are not [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rtfblog.com&amp;blog=18436446&amp;post=369&amp;subd=rtfblog&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>We are used to easily writing recursive calls and loops in procedural languages, but this doesn&#8217;t hold true in <a href="http://en.wikipedia.org/wiki/SQL"><abbr title="Simple Query Language">SQL</abbr></a>. Indeed, it depends on the <a href="http://en.wikipedia.org/wiki/Database_management_system"><abbr title="Database Management System">DBMS</abbr></a> used.</p>
<p>This article will focus on the ability to write recursive queries using <a href="http://en.wikipedia.org/wiki/Common_table_expressions">Common Table Expressions</a> (<abbr title="Common Table Expressions">CTE</abbr>). CTE are an addition from the <a href="http://en.wikipedia.org/wiki/SQL:1999">SQL 1999 standard</a> and are not yet available in all DBMS. As of today, CTE are at least compatible with:</p>
<ul>
<li>Microsoft SQL Server 2000 / 2005 / 2008</li>
<li>IBM DB2</li>
<li>Oracle 9.2</li>
<li>PostgreSQL</li>
</ul>
<p><span id="more-369"></span></p>
<h2>Definition and syntax</h2>
<p>A CTE is a temporary view with a very short life. It is only available in the <code>SELECT</code> following the declaration of the CTE, not longer!</p>
<p>The definition and the declaration is done in the same block, introduced by the <code>WITH</code> statement.</p>
<p><pre class="brush: sql;">
WITH expression_name [ ( column_name [,...n] ) ]
AS
(
   CTE_query_definition
)

/* You can use the CTE in the following select */
SELECT &lt;column_list&gt;
FROM   expression_name;

/* And this is it. The following select won't work */
SELECT &lt;column_list&gt;
FROM   expression_name;
</pre></p>
<p>As stated in the <abbr title="Microsoft Developer Network">MSDN</abbr>:</p>
<blockquote><p>Using a CTE offers the advantages of improved readability and ease of maintenance of complex queries. The query can be divided into separate, simple, logical building blocks. These simple blocks can then be used to build more complex, interim CTEs until the final result set is generated.</p></blockquote>
<p>Beware: the only situation in which CTE improve the speed of an SQL request is when they are used more than once per request. In this case, the CTE are evaluated only once. Otherwise they only improve its readability and maintainability. And even if it is a key point for any developper, the CTE feature I want to introduce here is the recursivity.</p>
<p><pre class="brush: sql;">
WITH expression_name [ ( column_name [,...n] ) ]
AS
(
   CTE_query_initialization

   UNION ALL

   CTE_query_recursion
)
</pre></p>
<p>A recursive function needs a base case, an inductive step and a stopping criterion. The initialization is done in the first <code>SELECT</code> while the inductive step is defined in the second one. Finally, the stopping criterion will be part of the <code>WHERE</code> statement of the second condition.</p>
<p>With such a feature it is now possible to dynamically build datasets and avoid table creation for example (as shown in the next part of this article).</p>
<h2>Basic example</h2>
<p>Before going further, a simple example may help to understand the power of CTE in SQL. The following code retrieves the value of the <a href="http://en.wikipedia.org/wiki/Factorial">factorial function</a></p>
<p>Reminder:</p>
<ul>
<li>factorial (0) = 1</li>
<li>factorial (1) = 1</li>
<li>factorial (n) = n! = n * factorial (n -1)</li>
<li>factorial (4) = 4! = 4 * factorial (3) = 4 * 3 * 2 * 1</li>
</ul>
<p>The following code returns the value of factorial (4). Amazing, isn&#8217;t it?</p>
<p><pre class="brush: sql;">
/* Code tested with MS SQL Server 2005/2008 */
with		cteFacto
as
(
   select	1			as I_FACTO,
			1			as FACTO
   union all
   select	I_FACTO + 1		as I_FACTO,
			(I_FACTO + 1) * FACTO	as FACTO
   from		cteFacto
   where	I_FACTO &lt; 9
)
/*
    I_FACTO indicates the factoriel we want
    FACTO retrieves its value
*/
select		FACTO
from		cteFacto
where		I_FACTO = 4  /* = 24 */
</pre></p>
<h2>Generate datasets with dates</h2>
<p>Dates manipulation is another, closer to concrete use cases, but still simple example of CTE in SQL.</p>
<p>Using CTE and recursivity, it is now very easy to generate this kind of dataset:</p>
<pre>AGENDA	                year    month   day
2011-01-01 00:00:00.000	2011	1	1
2011-01-02 00:00:00.000	2011	1	2
2011-01-03 00:00:00.000	2011	1	3
...
2011-01-27 00:00:00.000	2011	1	27
2011-01-28 00:00:00.000	2011	1	28
2011-01-29 00:00:00.000	2011	1	29
2011-01-30 00:00:00.000	2011	1	30
2011-01-31 00:00:00.000	2011	1	31</pre>
<p>And, it is as simple as this:</p>
<p><pre class="brush: sql;">
/* Code tested with MS SQL Server 2005/2008 */
declare		@startingDate	as	datetime
set			@startingDate	=	convert (datetime, '2011-01-01', 121)

/* Semicolons are mandatory when the with statement is not immediately after the go keyword  */

;with		cteAgenda
as
(
	select	@startingDate				as AGENDA
	union all
	select	DATEADD (day, 1, AGENDA)	as AGENDA
	from	cteAgenda
	where	agenda &lt; convert (datetime, '2011-02-01', 121)
)

select		AGENDA,
			YEAR (AGENDA)	as year,
			MONTH (AGENDA)	as month,
			DAY (AGENDA)	as day
from		cteAgenda
where		AGENDA &lt; convert (datetime, '2011-02-01', 121)
</pre></p>
<p>This kind of code may avoid the creation of a one-shot table by pushing values in a temporary table. Which, in my opinion, is a real benefit.</p>
<h2>Final points</h2>
<p>CTE are more than simple temporary views: they also allow the use of recursivity in SQL. Using CTE with temporary tables helps to create datasets that can be used in testing environment. They can also be used to explore datasets, or to recursivly apply operations on tree-structured datasets.</p>
<h2>Read more about CTE</h2>
<ul>
<li><a href="http://msdn.microsoft.com/en-us/library/ms190766.aspx">MSDN: CTE (EN)</a></li>
<li><a href="http://msdn.microsoft.com/en-us/library/ms186243.aspx">MSDN: Recursive CTE (EN)</a></li>
<li><a href="http://www.postgresql.org/docs/8.4/static/queries-with.html">PostgreSQL: CTE (EN)</a></li>
<li><a href="http://www.oracle-base.com/articles/misc/WithClause.php">Oracle 9i 2: CTE (EN)</a></li>
<li><a href="http://jab.developpez.com/tutoriels/db2/sqlrecursif/">IBM DB2: CTE (FR)</a></li>
<li><a href="http://www.simple-talk.com/content/print.aspx?article=260">CTE presentation (EN)</a></li>
<li><a href="http://sqlpro.developpez.com/cours/sqlserver/cte-recursives/"> CTE Recursives (FR)</a></li>
</ul>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rtfblog.wordpress.com/369/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rtfblog.wordpress.com/369/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/rtfblog.wordpress.com/369/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/rtfblog.wordpress.com/369/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/rtfblog.wordpress.com/369/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/rtfblog.wordpress.com/369/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/rtfblog.wordpress.com/369/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/rtfblog.wordpress.com/369/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/rtfblog.wordpress.com/369/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/rtfblog.wordpress.com/369/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/rtfblog.wordpress.com/369/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/rtfblog.wordpress.com/369/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/rtfblog.wordpress.com/369/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/rtfblog.wordpress.com/369/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rtfblog.com&amp;blog=18436446&amp;post=369&amp;subd=rtfblog&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://rtfblog.com/2011/06/27/recursion-in-sql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/145308e11029ad4a7849391d94d51b79?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">cperrod</media:title>
		</media:content>
	</item>
		<item>
		<title>Taking advantage of multithreaded environments with Ruby</title>
		<link>http://rtfblog.com/2011/05/25/taking-advantage-of-multithreaded-environments-with-ruby/</link>
		<comments>http://rtfblog.com/2011/05/25/taking-advantage-of-multithreaded-environments-with-ruby/#comments</comments>
		<pubDate>Wed, 25 May 2011 19:11:18 +0000</pubDate>
		<dc:creator>Xavier Noëlle</dc:creator>
				<category><![CDATA[A few words about...]]></category>
		<category><![CDATA[multicore]]></category>
		<category><![CDATA[multithread]]></category>
		<category><![CDATA[Parallelism]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[speed]]></category>

		<guid isPermaLink="false">http://rtfblog.wordpress.com/?p=315</guid>
		<description><![CDATA[If you have ever tried to write parallel scripts / applications using Ruby&#8217;s threads, you may have stumbled over the fact that, sometimes, some cores are left unused. You may be especially sad if you notice that your brand new war-machine, with 2 physical cores or more, is not fully exploited. Then, you would be [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rtfblog.com&amp;blog=18436446&amp;post=315&amp;subd=rtfblog&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>If you have ever tried to write parallel scripts / applications using Ruby&#8217;s threads, you may have stumbled over the fact that, sometimes, some cores are left unused. You may be especially sad if you notice that your brand new war-machine, with 2 physical cores or more, is not fully exploited.</p>
<p>Then, you would be right to wonder if using Ruby and taking advantage of multicore (i.e. writing multithreaded applications) are compatible.</p>
<p>The simple answer is yes. Let&#8217;s dig into the more complicated answers: we&#8217;ll first explain how Ruby&#8217;s threads work, then explain why they sometimes seem to be broken, and eventually suggest four efficient solutions to get rid of their limitations.</p>
<h3><span id="more-315"></span>Ruby threading models</h3>
<p>As explained in my <a href="http://rtfblog.wordpress.com/2011/03/21/why-you-should-probably-not-bother-about-ruby-s-speed/">previous article about Ruby&#8217;s speed</a>, the 1.8.x and 1.9.x branches of Ruby are coexisting since 2008. One of the most important performance tweaks between the two mainstream interpreters<sup>1</sup> is related to the threading model itself.</p>
<p>Prior to the 1.9.x branch, Ruby, with <abbr title="Matz's Ruby Interpreter">MRI</abbr>, was using green (user-level) threads. With this threading model, one can map only one application per kernel-level scheduled entity (simply put, an application can use only one kernel thread); thus, the kernel does not even know if your application is multithreaded or not. This approach has several advantages, such as:</p>
<ul>
<li>providing threading on environments which do not support threading (it is handled by the application itself);</li>
<li>reducing the cost of context-switching (switching between threads).</li>
</ul>
<p>The choice of using green threads was made for Ruby <a title="Shades of Gray: The Ruby VM: Episode III" href="http://blog.grayproductions.net/articles/the_ruby_vm_episode_iii">14 years ago</a>, for compatibility reasons, when a lot of systems did not provide threading support.</p>
<p>But the major drawback of this threading model is that it cannot benefit from multi-core processors. This also means that threads may block each other during I/O operations, because they share the same execution context.</p>
<p>With the release of <abbr title="Yet Another Ruby VM">YARV</abbr>, Ruby 1.9.x now uses kernel threads; this means that every single Ruby thread is mapped to a kernel thread and can be run on a different core, and thus enables a single Ruby script to use more than one core.</p>
<h3>The Global Interpreter Lock (GIL)</h3>
<p>The latter model sounds perfect and allows scripts to run more efficiently in a lot of concurrency situations.</p>
<p><em>But</em>, everything is not perfect in the shiny kernel threads&#8217; world: the Python and Ruby lovers among you may have already heard about the <a href="http://en.wikipedia.org/wiki/Global_Interpreter_Lock">Global Interpreter Lock</a>, a huge mutual exclusion lock (aka mutex), preventing multiple Ruby threads to use the interpreter at the same time.</p>
<p>Two Ruby threads may then not run pure Ruby code (more precisely, use its API) at the same time. This problem is illustrated by running the following code:</p>
<p><pre class="brush: ruby;">
2.times() do
  Thread.new() do
    a = Array.new()
    a &lt;&lt; 1
    a.clear()
  end
end
</pre></p>
<p>This code starts two threads which will perform an array instantiation, append the “1” value to it, and then empty it. Let&#8217;s schedule this by hand, in a pure didactic and fictitious way; red (resp. green) blocks represent periods of inactivity (resp. activity):</p>
<p><a href="http://rtfblog.files.wordpress.com/2011/05/rtfblogrubygil.png"><img src="http://rtfblog.files.wordpress.com/2011/05/rtfblogrubygil.png?w=300&#038;h=209" alt="Ruby GIL illustrated" title="RTFBlogRubyGIL" width="300" height="209" class="aligncenter size-medium wp-image-324" /></a></p>
<p>What is striking in this figure is the forced inactivity of the B thread when the A thread is running and vice-versa.</p>
<p>The problem is different when some pure C code is involved. As stated in the previous article, Ruby features easy interactions with C. Then we may simply add a call to some random C code (provided that it explicitly releases the GIL, and then doesn&#8217;t use the Ruby API), right after the array instantiation, and the figure becomes:</p>
<p><a href="http://rtfblog.files.wordpress.com/2011/05/rtfblogrubygilmysql.png"><img src="http://rtfblog.files.wordpress.com/2011/05/rtfblogrubygilmysql.png?w=350&#038;h=224" alt="Ruby GIL illustrated with C code" title="RTFBlogRubyGILmysql" width="350" height="224" class="aligncenter size-medium wp-image-325" /></a></p>
<p>Much more interesting! This illustrates clearly that the problem only occurs when the Ruby API is involved.</p>
<h3>Getting rid of the Global Interpreter Lock (GIL)</h3>
<p>There are four main solutions to the GIL restriction (two of them are the subject of in-depth articles, which will be linked directly below):</p>
<ul>
<li>Run your script on a different VM: for example, JRuby and Rubinius have gotten rid of the GIL, so you might want to try them out.</li>
<li>Wait for a new mainstream VM: Koichi Sasada (the creator of YARV) announced that  <a title="Shades of Gray: The Ruby VM: Episode III" href="http://blog.grayproductions.net/articles/the_ruby_vm_episode_iii">he may be working on a multi-VM version of the interpreter</a>, in which the GIL would no longer exist… we&#8217;ll stay tuned about that!</li>
<li>Write long and blocking parts in C: extensions can run in parallel, given this simple constraint: you must manually ask the Ruby VM to release the GIL for the current thread. But after doing so, you shall not call, directly or not, any function of Ruby&#8217;s API, since this would lead to an undefined behavior. Some gems take advantage of this solution, such as <a href="https://github.com/brianmario/mysql2">mysql2</a>, which allows to execute Ruby code while waiting for the result of a MySQL request (the mysql gem does not allow that).</li>
<li>Use separate processes: if you want to get rid of the GIL, run multiple interpreters (quite straightforward)! Ruby ships with a good <abbr title="Inter-Process Communication">IPC</abbr> library named DRb, which makes tasks distribution really easy.</li>
</ul>
<h3>Closing comments</h3>
<p>This article tried to depict what you can expect from Ruby in terms of parallelism. It was mainly aimed at convincing you that green threads in Ruby 1.8, or the GIL in Ruby, are no show-stoppers, even if they require a little adaptation. If you&#8217;re curious about the last two solutions mentioned above, you are strongly encouraged to stay tuned for the in-depth articles:</p>
<hr />
<ol>
<li>We won&#8217;t cover other interpreters&#8217; implementation in this article.</li>
</ol>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rtfblog.wordpress.com/315/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rtfblog.wordpress.com/315/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/rtfblog.wordpress.com/315/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/rtfblog.wordpress.com/315/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/rtfblog.wordpress.com/315/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/rtfblog.wordpress.com/315/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/rtfblog.wordpress.com/315/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/rtfblog.wordpress.com/315/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/rtfblog.wordpress.com/315/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/rtfblog.wordpress.com/315/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/rtfblog.wordpress.com/315/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/rtfblog.wordpress.com/315/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/rtfblog.wordpress.com/315/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/rtfblog.wordpress.com/315/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rtfblog.com&amp;blog=18436446&amp;post=315&amp;subd=rtfblog&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://rtfblog.com/2011/05/25/taking-advantage-of-multithreaded-environments-with-ruby/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/b111270483636e6535de8d04bc54a552?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">xaviernoelle</media:title>
		</media:content>

		<media:content url="http://rtfblog.files.wordpress.com/2011/05/rtfblogrubygil.png?w=300" medium="image">
			<media:title type="html">RTFBlogRubyGIL</media:title>
		</media:content>

		<media:content url="http://rtfblog.files.wordpress.com/2011/05/rtfblogrubygilmysql.png?w=300" medium="image">
			<media:title type="html">RTFBlogRubyGILmysql</media:title>
		</media:content>
	</item>
		<item>
		<title>An introduction to search-based applications</title>
		<link>http://rtfblog.com/2011/04/11/introduction-sba/</link>
		<comments>http://rtfblog.com/2011/04/11/introduction-sba/#comments</comments>
		<pubDate>Mon, 11 Apr 2011 08:49:17 +0000</pubDate>
		<dc:creator>Clément Perrod</dc:creator>
				<category><![CDATA[A few words about...]]></category>
		<category><![CDATA[analysis]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[Information Access]]></category>
		<category><![CDATA[restitution]]></category>
		<category><![CDATA[SBA]]></category>
		<category><![CDATA[Search engine]]></category>
		<category><![CDATA[search-based applications]]></category>

		<guid isPermaLink="false">http://rtfblog.wordpress.com/?p=68</guid>
		<description><![CDATA[Search Based Applications (SBA) are applications based on search engines. They are designed for users who want to discover and analyse information. They usually require processing large amounts of data, processing data in real-time or handling unstructured or semi-structured data, among others. To handle these requirements, they benefit from the appropriate processes already used by [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rtfblog.com&amp;blog=18436446&amp;post=68&amp;subd=rtfblog&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p style="text-align:justify;">Search Based Applications (<abbr title="Search Based Applications">SBA</abbr>) are applications based on search engines. They are designed for users who want to discover and analyse information. They usually require processing large amounts of data, processing data in real-time or handling unstructured or semi-structured data, among others. To handle these requirements, they benefit from the appropriate processes already used by search engines (scalable foundations and natural language processing, for example).<br />
Input data can be structured (databases…) but also unstructured (Office documents, PDF, mails…) or even coming from other applications (<abbr title="Enterprise Resource Planning">ERP</abbr>, <abbr title="Customer Relationship Management">CRM</abbr>, intranet, extranet…).</p>
<p style="text-align:justify;">Unlike traditional search engines, SBA provide ad-hoc interfaces to data (dashboards, mashups…), so that the user can access the right information without necessarily having to perform requests manually (in the context of <abbr title="Business Intelligence">BI</abbr>, for example, it allows him to take the good decision on time by giving him a relevant view of the data).</p>
<p style="text-align:justify;">Notice the difference between discovering and searching: when searching, the user knows what he is looking for; when discovering, he starts by searching something, which brings him to a final point he may not have expected. Think about it: discovering is what we need when taking decisions. Why? Because even if we know what information we need we may not know how to get it. Discovering helps users to take better decisions.</p>
<h2 style="text-align:justify;"><span id="more-68"></span>The players</h2>
<p style="text-align:justify;">The main SBA platform editors are also <a href="http://en.wikipedia.org/wiki/Information_access">Information Access market</a> players. Most of them have more than five years of experience in providing indexing tools to their clients, which gives them some credibility.</p>
<p style="text-align:justify;">The current leader is Endeca with <a href="http://www.endeca.com/en/products/endeca_latitude.html">Endeca Lattitude</a>, which is a big American company also operating in Europe and Asia. So they have clients and offices all over the world. Then comes Attivio with the <a href="http://www.attivio.com/active-intelligence/aie-platform.html">AIE Platform</a>. The main difference is that Attivio does not provide only a web client but also a desktop one where any user can write SQL-like requests on any kind of data. Two french companies are also in the SBA market. The biggest one is Exalead with <a href="http://www.exalead.com/software/products/cloudview/360/">Exalead CloudView 360</a>. They are mainly doing business in the French market but are trying to grow up outside the Europe (even more since Dassault System bought them). Finally, the last one and the smallest: <a href="http://www.sinequa.com/product.aspx">Sinequa</a>. It is a young company 100 % focused on the SBA market.</p>
<p style="text-align:justify;">The following “Magic Quadrant” comes up as a summary of the different editors.</p>
<p style="text-align:center;"><a href="http://rtfblog.files.wordpress.com/2011/04/magic-quadrant.png"><img class="aligncenter" src="http://rtfblog.files.wordpress.com/2011/04/magic-quadrant.png?w=600" alt="SBA Magic Quadrant" /></a></p>
<h2 style="text-align:justify;">General Anatomy of an SBA</h2>
<p style="text-align:justify;">Three steps are present in a SBA project, whatever the chosen solution is (at least it is true for Attivio, Endeca and Exalead).</p>
<p style="text-align:justify;">First, the appplication needs to collect data by connecting to all sources. Fortunately, SBA provides <abbr title="Application Programming Interfaces">APIs</abbr> and tools to make this easy. As of today, connectors have already been developed for:</p>
<ul>
<li style="text-align:justify;">Databases (through JDBC/ODBC)</li>
<li style="text-align:justify;">Filesystems</li>
<li style="text-align:justify;">Internet / extranet / intranet</li>
<li style="text-align:justify;">E-mails</li>
<li style="text-align:justify;"><abbr title="Lightweight Directory Access Protocol"><a href="http://fr.wikipedia.org/wiki/Lightweight_Directory_Access_Protocol"> LDAP</a></abbr></li>
<li style="text-align:justify;"><abbr title="Enterprise Resource Planning"><a href="http://en.wikipedia.org/wiki/Enterprise_resource_planning">ERP</a></abbr>, <abbr title="Customer Relationship Management"><a href="http://en.wikipedia.org/wiki/Customer_relationship_management">CRM</a></abbr>, <abbr title="Content Management Systems"><a href="http://en.wikipedia.org/wiki/Content_management_system"> CMS</a></abbr></li>
</ul>
<p style="text-align:justify;">If a connector does not exist, it is possible to create it or ask for it. In this part of the project, it is also possible to transform unstructured data in semi-structured one by using semantic and analytic processes.</p>
<p style="text-align:justify;">Then comes the indexing tool. This part is the easiest one because it does not require any development on the client site. This is where the search engine experience and intelligence comes in: the application automatically knows how to collect all data according to the configuration and indexes it, in order to be able to retrieve all information when needed.</p>
<p style="text-align:justify;">The project ends with the restitution part. Building dashboards and pages is almost as important as connecting to data. Once again, editors provide APIs and tools for this part, so small effort is needed to produce interesting and efficient layouts.</p>
<p style="text-align:justify;">Generally, when a client starts an SBA project, he only has an idea of the expected result and the needs evolve with it. Dealing with such constraints is possible because these projects are based on Agile software developments. According to Exalead experience in this kind of projects, the average needed time is around a year with loops of 2 months.</p>
<h2 style="text-align:justify;">Going further</h2>
<p style="text-align:justify;">The SBA market is still very young but it may become a huge one in the future. For example, clients with BI products are asking for such projects to complete their BI solution.</p>
<p style="text-align:justify;">If you are looking for complementary information about SBA, you may also search for <abbr title="Unified Information Access">UIA</abbr> (Unified Information Access) or <abbr title="Unified Business Information">UBI</abbr> (Unified Business Information).</p>
<p style="text-align:justify;">The following articles may also give you more information:</p>
<ul style="text-align:justify;">
<li><a href="http://www.information-management.com/newsletters/business_intelligence_bi_search-10017332-1.html">The BI-Search evolution (Endeca)</a> (EN)</li>
<li><a href="http://www.bi-bestpractices.com/view-articles/5638Enterprise">BI Search : Implementation Considerations (Information Builders)</a> (EN)</li>
<li><a href="http://www.kmworld.com/Articles/Editorial/Feature/Search-based-applications-support-critical-decision-making-66062.aspx">Search-based applications support critical decision-making</a> (EN)</li>
<li><a href="http://www.attivio.com/blog/57-unified-information-access/503-who-needs-unified-information-access-anyway.html">Who Needs Unified Information Access, Anyway? (Attivio)</a> (EN)</li>
<li><a href="http://www.qualitystreet.fr/2007/11/20/methodes-agiles-un-belle-definition/">Méthodes AGILES : une belle définition</a> (FR)</li>
<li><a href="http://en.wikipedia.org/wiki/Search-based_application">Wikipedia article</a> (EN)</li>
</ul>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rtfblog.wordpress.com/68/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rtfblog.wordpress.com/68/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/rtfblog.wordpress.com/68/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/rtfblog.wordpress.com/68/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/rtfblog.wordpress.com/68/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/rtfblog.wordpress.com/68/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/rtfblog.wordpress.com/68/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/rtfblog.wordpress.com/68/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/rtfblog.wordpress.com/68/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/rtfblog.wordpress.com/68/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/rtfblog.wordpress.com/68/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/rtfblog.wordpress.com/68/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/rtfblog.wordpress.com/68/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/rtfblog.wordpress.com/68/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rtfblog.com&amp;blog=18436446&amp;post=68&amp;subd=rtfblog&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://rtfblog.com/2011/04/11/introduction-sba/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/145308e11029ad4a7849391d94d51b79?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">cperrod</media:title>
		</media:content>

		<media:content url="http://rtfblog.files.wordpress.com/2011/04/magic-quadrant.png" medium="image">
			<media:title type="html">SBA Magic Quadrant</media:title>
		</media:content>
	</item>
		<item>
		<title>Why you should probably not bother about Ruby&#8217;s speed</title>
		<link>http://rtfblog.com/2011/03/21/why-you-should-probably-not-bother-about-ruby-s-speed/</link>
		<comments>http://rtfblog.com/2011/03/21/why-you-should-probably-not-bother-about-ruby-s-speed/#comments</comments>
		<pubDate>Mon, 21 Mar 2011 22:42:43 +0000</pubDate>
		<dc:creator>Xavier Noëlle</dc:creator>
				<category><![CDATA[A few words about...]]></category>
		<category><![CDATA[benchmarks]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[speed]]></category>

		<guid isPermaLink="false">http://rtfblog.wordpress.com/?p=9</guid>
		<description><![CDATA[The expressivity and power of Ruby make it a really efficient programming language. Its dynamic nature results in lots of enjoyable benefits (introspection, dynamic class reopening…); it is also responsible for a part of its performances, which are sometimes believed to be poor. Is Ruby really slow? While being obviously slower than most natively compiled [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rtfblog.com&amp;blog=18436446&amp;post=9&amp;subd=rtfblog&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>The expressivity and power of Ruby make it a really efficient programming language. Its dynamic nature results in lots of enjoyable benefits (introspection, dynamic class reopening…); it is also responsible for a part of its performances, which are sometimes believed to be poor.</p>
<p>Is Ruby really slow? While being obviously slower than most natively compiled languages, is the performance gap really worth noticing and should it prevent you from using this great language?</p>
<p>If all you&#8217;re coming for is pure performance benchmarks, you may directly skip to the last part of this article (&#8220;Lies, damned lies, and benchmarks&#8221;), since this article does not aim at benchmarking Ruby.</p>
<h3><span id="more-9"></span>ruby &#8211;version</h3>
<p>Depending on your OS or the way you installed Ruby on your computer, you may be facing two different major releases of Ruby. If you take a look at Ruby&#8217;s history, you can notice that the 1.8.x branch started in 2003 and was joined by the 1.9.x branch at the very beggining of 2009. Since then, these two versions are coexisting, while being different in a number of ways.</p>
<p>The most interesting change is related to the interpreter itself: <acronym title="Yet Another Ruby VM">YARV</acronym>, the mainstream Ruby 1.9.x interpreter, is now dealing with bytecode, rather than constantly parsing and executing unoptimized Ruby code. The addition of a few other optimizations induced a great speed boost for most Ruby scripts (about three times faster on average, according to benchmarks which are legion on the Web: for example, <a title="YARV speedup" href="http://rubychan.de/share/yarv_speedups.html">here</a> and <a title="Ruby real world performances" href="http://on-ruby.blogspot.com/2007/04/some-real-world-performance-notes-on.html">here</a>).</p>
<p>Sadly, most beliefs about Ruby are based on the old 1.8.x branch, which was the most used branch until now, but tends to be replaced by newer versions; a great effort is being made to migrate major gems (Ruby packages, such as Rails) and applications to the 1.9.x branch. The new Ruby interpreter comes with a revision of the language itself, which makes this migration not as easy as it seems and explains why some people are still late to the party.</p>
<h3>One language to rule them all, and in the runtime bind them</h3>
<p>Aside from the well known <acronym title="Matz Ruby Interpreter">MRI</acronym> and <acronym title="Yet Another Ruby VM">YARV</acronym>, which are respectively shipped with Ruby 1.8.x and Ruby 1.9.x, some other mature Ruby interpreters are available and quite widely used. They feature some additional or structural refinements, which make them better suited than the mainstream interpreters in some situations. Two of the most notable challengers are:</p>
<ul>
<li> <a title="JRuby homepage" href="http://jruby.org/">JRuby</a>: an interpreter based on the Java Virtual Machine, providing an easy integration with Java libraries as well as the obvious advantages of running inside the JVM;</li>
<li> <a title="Rubinius homepage" href="http://rubini.us/">Rubinius</a>: an interpreter written in C++, which features Just-in-time (<acronym title="Just-in-time">JIT</acronym>) native machine code compilation.</li>
</ul>
<p>These interpreters outperform the standard interpreters for some specific problematics (one of them being parallelism efficiency, which will be the main topic of an upcoming article) and may be worth benchmarking when performances become a concern, before deciding to drop Ruby.</p>
<h3>C for hostpots, Ruby for everything else</h3>
<p>Most of the standard Ruby library, as well as a number of gems (Ruby packages), is written in pure C. Indeed, Ruby features easy interactions with C and C++: you can use the Ruby API in your C code and your Ruby code can, in turn, easily retrieve results from your C code. This is roughly achieved by using one or more C files, a file composed of a few lines of Makefile-like syntax which will build a library for you, a function call and… that&#8217;s it!<sup>[1]</sup></p>
<p>Knowing that, it would be wise to reconsider Pareto&#8217;s principle: most of the time, 20 % of your code is responsible for 80 % of your application&#8217;s runtime. Rewriting these slow parts in a compiled language like C, while keeping structural parts human-readable by using a high-level language should be the way to go, when possible (i.e. most of the time); that is exactly the Ruby way of thinking. Moreover, when profiling your applications, you will often notice that the slow parts of your application are completely independent from the language you&#8217;re using.</p>
<p>And believe me: most of the time, you won&#8217;t even need C at all! I have myself never really needed to rewrite parts of my applications in C, even when raw performances were a vital concern. In fact, the only time I really thought I needed it led me to a complete waste of time, since I was trying to improve performances by focusing on the wrong problem. This is not to say “never use C” but rather “use C when all other reasonable options failed”; mixing code may reduce your source code readability and maintainability.</p>
<h3>Lies, damned lies, and benchmarks</h3>
<p>If you expected benchmarks in this article, you will be disappointed. The only general truth that should come to your mind is the following ranking<sup>[2]</sup> (sorted by decreasing performance):</p>
<ul>
<li>Natively compiled languages (C, C++, Fortran, Pascal…)</li>
<li>Byte-compiled languages (Ruby 1.9.x, Python, Java…)</li>
<li>Interpreted languages (PHP, Shell-scripting languages, Ruby 1.8.x…)</li>
</ul>
<p>Everything else is usually a waste of time for general applications, especially when you are allowed to mix compiled chunks of code in your Ruby or Python application. Keep in mind that the time you save by using a more powerful (in terms of expressivity, readability, standard structures…) language can be used to throw up some heavy algorithmic as well as parallelization optimizations, which will make a greater difference, most of the time.</p>
<p>Well, if you really want benchmarks (because I know you&#8217;ll be upset otherwise), you may want to follow <a title="Computer Language Benchmarks Game" href="http://shootout.alioth.debian.org/u32/benchmark.php?test=all&amp;lang=all">this link</a> (but I warned you!).</p>
<h3>Conclusion</h3>
<p>I hope this article convinced you that considering Ruby as a slow language is mostly false and generally irrelevant. For those of you who need extreme performances, a natively compiled language like C or C++ will certainly perform better in some cases.</p>
<p>But if you don&#8217;t fit in this category and, nevertheless, plan to drop Ruby<sup>[3]</sup> just because you think it won&#8217;t be fast enough for you, you may want to reconsider your thoughts…</p>
<hr />
<ol>
<li> This will be discussed more thoroughly in an upcoming article about Ruby and parallelism.</li>
<li> Languages are categorized with respect to their current main implementation (eg. MRI for Ruby 1.8, YARV for Ruby 1.9…).</li>
<li> The same reasoning applies to Python as well.</li>
</ol>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rtfblog.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rtfblog.wordpress.com/9/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/rtfblog.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/rtfblog.wordpress.com/9/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/rtfblog.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/rtfblog.wordpress.com/9/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/rtfblog.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/rtfblog.wordpress.com/9/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/rtfblog.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/rtfblog.wordpress.com/9/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/rtfblog.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/rtfblog.wordpress.com/9/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/rtfblog.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/rtfblog.wordpress.com/9/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rtfblog.com&amp;blog=18436446&amp;post=9&amp;subd=rtfblog&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://rtfblog.com/2011/03/21/why-you-should-probably-not-bother-about-ruby-s-speed/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/b111270483636e6535de8d04bc54a552?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">xaviernoelle</media:title>
		</media:content>
	</item>
		<item>
		<title>Improve your Internet upload bandwidth management by configuring your Linux router</title>
		<link>http://rtfblog.com/2011/03/12/improve-your-internet-upload-bandwidth-management-by-configuring-your-linux-router/</link>
		<comments>http://rtfblog.com/2011/03/12/improve-your-internet-upload-bandwidth-management-by-configuring-your-linux-router/#comments</comments>
		<pubDate>Sat, 12 Mar 2011 17:48:41 +0000</pubDate>
		<dc:creator>Albin Kauffmann</dc:creator>
				<category><![CDATA[HowTo]]></category>
		<category><![CDATA[config]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Qos]]></category>
		<category><![CDATA[router]]></category>
		<category><![CDATA[tc]]></category>

		<guid isPermaLink="false">http://rtfblog.wordpress.com/?p=87</guid>
		<description><![CDATA[If you are running a Torrent, FTP or whatever kind of server behind your DSL link, you have probably noticed that interactive sessions get really slow (Web browsing, SSH…). As a first solution, you can of course configure your Torrent or FTP server to limit its upload but it&#8217;s not fully optimized as this wouldn&#8217;t [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rtfblog.com&amp;blog=18436446&amp;post=87&amp;subd=rtfblog&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>If you are running a Torrent, FTP or whatever kind of server behind your DSL link, you have probably noticed that interactive sessions get really slow (Web browsing, SSH…). As a first solution, you can of course configure your Torrent or FTP server to limit its upload but it&#8217;s not fully optimized as this wouldn&#8217;t use 100 % of your upload bandwidth.</p>
<p><span id="more-87"></span></p>
<p style="font-size:.8em;padding-left:30px;"><a href="http://www.linuxembedded.fr/2011/06/utiliser-tc-pour-optimiser-lupload">(French version of this article)</a></p>
<p>Before introducing a solution, let&#8217;s briefly explain what is happening. Typical Ethernet modems handle packets with the same priority. Only IP packets with a specific “Type of Service” (ToS) benefit from a special treatment and are sent in priority. This allows services like VoIP to stream data in real-time.</p>
<p>The goal of this article is to show how a Linux router can be configured to control your upload bandwidth by setting up different priorities to the network traffic. This task is achieved by using the Linux traffic control functionality (<code>tc</code>).</p>
<p>Controlling your download traffic, while possible with TCP connections, is much more complicated. Indeed, you can&#8217;t access your ISP routers in order to set up your own configuration. Then, your only possibility is to drop received packets in order to decrease the speed of TCP connections. This works because the TCP protocol automatically adapts the speed of a session. This article doesn&#8217;t get into download bandwidth control but you should find interesting links in resources. Finally, remember that ISP are implementing QoS so you don&#8217;t have to worry about the priority of your VoIP/RTP/… connections.</p>
<h2>Overview</h2>
<p>In this article, I suppose a Linux box is already configured as a router:</p>
<p><a href="http://rtfblog.files.wordpress.com/2011/03/tc-overview3.png"><img class="alignnone size-full wp-image-152" title="tc-overview" src="http://rtfblog.files.wordpress.com/2011/03/tc-overview3.png?w=600" alt=""   /></a></p>
<p>Note: the IPv6 configuration is not covered in this article but it should be pretty similar.</p>
<p>In order to control the order in which packets are sent to the Internet, packets need to be queued and sorted at the Linux Box level:</p>
<p><a href="http://rtfblog.files.wordpress.com/2011/03/tc-overview-queue1.png"><img class="alignnone size-full wp-image-154" title="tc-overview-queue" src="http://rtfblog.files.wordpress.com/2011/03/tc-overview-queue1.png?w=600" alt=""   /></a></p>
<p>By default, packets are queued at the modem level, that&#8217;s why this article firstly shows how to force the queuing to be done by the Linux box. Then, <code>tc</code> is mentioned to sort packets and <code>iptables</code> to mark them.</p>
<h2>Force queuing at the Linux Box level</h2>
<p>The first thing to do is to configure the Linux Box so that it fully controls the outgoing bandwidth. As already mentioned, outgoing traffic needs to be queued by the Linux Box and not by the DSL modem.</p>
<p>Unfortunately, the only way is to limit the Linux Box upload bandwidth so that the modem queue never gets filled (in fact, there might exist some modem allowing to set the size of the queue but I&#8217;m not even sure it will help).</p>
<p>To do so, Linux offers a <em>Traffic Control</em> service (<code>tc</code>). <code>tc</code> allows to define a tree of <em>qdiscs</em> (where packets are actually queued) and <em>classes</em>. A <em>class</em> contains one or several <em>qdisc(s)</em> and allows to define where/how packets are queued. In this article, two <em>qdiscs</em> are going to be used:</p>
<ul>
<li>HTB (Hierarchy Token Bucket): HTB allows to shape network traffic;</li>
<li>SFQ (Stochastic Fairness Queueing): SFQ allows packets of each session to be send in turn (all sessions are then treated equally).</li>
</ul>
<p>For more information, please read the man pages of <a href="http://linux.die.net/man/8/tc"><code>tc</code></a>, <a href="http://linux.die.net/man/8/tc-htb"><code>tc-htb</code></a> and <a href="http://linux.die.net/man/8/tc-sfq"><code>tc-sfq</code></a>.</p>
<p>So, here are the commands to limit your upload to <code>$RATEUP</code> (<code>$DEV == eth1</code>):</p>
<div dir="ltr">
<div>
<pre>ip link set dev $DEV qlen $QLEN mtu $MTU

tc qdisc add dev $DEV root handle 1: htb default 1
  tc class add dev $DEV parent 1: classid 1:1 htb rate ${RATEUP}kbit
    tc qdisc add dev $DEV parent 1:1 handle 10: sfq perturb 10</pre>
</div>
</div>
<p>In a few words, these commands:</p>
<ol>
<li>decrease the size of the queue and set the MTU to something more appropriate for the DSL connection (<code>$QLEN=100</code> and <code>$MTU=modem_value</code>);</li>
<li>replace the default queue by a <em>HTB</em> qdisc;</li>
<li>add a class to the <em>HTB</em> qdisc to limit the bandwidth to <code>${RATEUP}kbit</code>;</li>
<li>add a <em>SFQ</em> qdisc to this class.</li>
</ol>
<h2>Sort packets with <code>tc</code></h2>
<p>The <em>HTB</em> class system allows to define several queues (<em>qdisc</em>) with different priorities. This way, packets waiting to be sent are sorted and sent (the higher priority is 0):</p>
<div dir="ltr">
<div>
<pre>tc qdisc add dev $DEV root handle 1: htb default 12
  tc class add dev $DEV parent 1: classid 1:1 htb rate ${RATEUP}kbit

    tc class add dev $DEV parent 1:1 classid 1:10 htb rate ${RATEMIN}kbit \
      ceil ${RATEUP}kbit prio 0
    tc class add dev $DEV parent 1:1 classid 1:11 htb rate ${RATEMIN}kbit \
      ceil ${RATEUP}kbit prio 1
    tc class add dev $DEV parent 1:1 classid 1:12 htb rate ${RATEMIN}kbit \
      ceil ${RATEUP}kbit prio 2
    tc class add dev $DEV parent 1:1 classid 1:13 htb rate ${RATEMIN}kbit \
      ceil ${RATEUP}kbit prio 3

      tc qdisc add dev $DEV parent 1:10 handle 10: sfq perturb 10
      tc qdisc add dev $DEV parent 1:11 handle 11: sfq perturb 10
      tc qdisc add dev $DEV parent 1:12 handle 12: sfq perturb 10 # def. queue
      tc qdisc add dev $DEV parent 1:13 handle 13: sfq perturb 10

tc filter add dev $DEV parent 1: prio 0 protocol ip handle 10 fw flowid 1:10
tc filter add dev $DEV parent 1: prio 0 protocol ip handle 11 fw flowid 1:11
tc filter add dev $DEV parent 1: prio 0 protocol ip handle 12 fw flowid 1:12
tc filter add dev $DEV parent 1: prio 0 protocol ip handle 13 fw flowid 1:13</pre>
</div>
</div>
<p>This script creates 4 queues with priorities going from 0 to 3 and with a minimum rate (<code>$RATEMIN</code>). This minimum rate allows low priority applications to always have access to the Internet, that is applications won&#8217;t fail with a network timeout because another high priority application is using the whole bandwidth.</p>
<p>The queue defined with the <em>classid</em> 1:12 is the default one and is used if no <code>tc filter</code> command defines another behavior. In this example, <code>tc filter</code> commands allow to sort packets according to the tag previously set by <code>iptables</code> (then, untagged packets use the default qdisc). The next section explains how packets are tagged.</p>
<h2>Mark packets with <code>iptables</code></h2>
<p>If you already know how to use <code>iptables</code>, marking packets is really easy. Rules must be added to the <code>mangle</code> table and to the <code>POSTROUTING</code> chain. Here is a small example which shows how packets could be sorted with the previous <code>tc</code> configuration:</p>
<div dir="ltr">
<div>
<pre># High priority for ping packets
iptables -t mangle -A POSTROUTING -p icmp -j MARK --set-mark 10

# Default for low port outgoing connections (clients)
iptables -t mangle -A POSTROUTING -p tcp --dport 0:1024 -j MARK --set-mark 11

# Default for low port ingoing connections (servers)
iptables -t mangle -A POSTROUTING -p tcp --sport 0:1024 -j MARK --set-mark 12

# High priority for DNS, SIP and ACK packets
iptables -t mangle -A POSTROUTING -p udp -j MARK --set-mark 10
iptables -t mangle -A POSTROUTING -p tcp -m length --length :64 -j MARK \
  --set-mark 10 # Small packets are generally ACKs
iptables -t mangle -A POSTROUTING -p tcp --dport sip -j MARK --set-mark 10
iptables -t mangle -A POSTROUTING -p tcp --dport sip-tls -j MARK --set-mark 10

# High priority for interactive sessions
iptables -t mangle -A POSTROUTING -p tcp --dport ssh -j MARK --set-mark 11
iptables -t mangle -A POSTROUTING -p tcp --sport ssh -j MARK --set-mark 11

# Low priority for FTP data and torrent outbound traffic
iptables -t mangle -A POSTROUTING -p tcp --sport MINPORT:MAXPORT -j MARK \
  --set-mark 14
iptables -t mangle -A POSTROUTING -p tcp --sport 6881:6999 -j MARK \
  --set-mark 14</pre>
</div>
</div>
<p>The configuration is now finished but you need to run tests in order to determine the best value of <code>$RATEUP</code> (<code>tc</code> script). To do so, run a ping to a remote host and a program which uploads data. As long as the ping stays low, you can try to increase <code>$RATEUP</code>. If the ping is high, you need to decrease <code>$RATEUP</code>.</p>
<h2>Conclusion</h2>
<p>You can now impress your friends by keeping a small ping while running a lot of services behind your DSL connection <img src='http://s0.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><code>tc</code> offers a lot more possibilities that can be found by reading man pages and links given in the <em>Resources</em> section. You can also download my <code>tc-restore</code> script which sets the <code>tc</code> configuration on a Debian like system.</p>
<h2>Resources</h2>
<ul>
<li>My <a href="https://gist.github.com/866472">tc-restore</a> script</li>
<li>man pages of <a href="http://linux.die.net/man/8/tc"><code>tc</code></a>, <a href="http://linux.die.net/man/8/tc-htb"><code>tc-htb</code></a>, <a href="http://linux.die.net/man/8/tc-sfq"><code>tc-sfq</code></a>&#8230;</li>
<li><a href="http://lartc.org/">http://lartc.org</a> and especially <a href="http://lartc.org/howto/lartc.qdisc.html">http://lartc.org/howto/lartc.qdisc.html</a></li>
<li><a href="http://tldp.org/HOWTO/Traffic-Control-HOWTO/index.html">http://tldp.org/HOWTO/Traffic-Control-HOWTO/index.html</a></li>
</ul>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rtfblog.wordpress.com/87/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rtfblog.wordpress.com/87/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/rtfblog.wordpress.com/87/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/rtfblog.wordpress.com/87/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/rtfblog.wordpress.com/87/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/rtfblog.wordpress.com/87/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/rtfblog.wordpress.com/87/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/rtfblog.wordpress.com/87/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/rtfblog.wordpress.com/87/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/rtfblog.wordpress.com/87/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/rtfblog.wordpress.com/87/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/rtfblog.wordpress.com/87/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/rtfblog.wordpress.com/87/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/rtfblog.wordpress.com/87/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rtfblog.com&amp;blog=18436446&amp;post=87&amp;subd=rtfblog&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://rtfblog.com/2011/03/12/improve-your-internet-upload-bandwidth-management-by-configuring-your-linux-router/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/a628b653fd3e853835a1ff16248d65af?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">albinkauffmann</media:title>
		</media:content>

		<media:content url="http://rtfblog.files.wordpress.com/2011/03/tc-overview3.png" medium="image">
			<media:title type="html">tc-overview</media:title>
		</media:content>

		<media:content url="http://rtfblog.files.wordpress.com/2011/03/tc-overview-queue1.png" medium="image">
			<media:title type="html">tc-overview-queue</media:title>
		</media:content>
	</item>
		<item>
		<title>Hello world !</title>
		<link>http://rtfblog.com/2010/12/15/hello-world/</link>
		<comments>http://rtfblog.com/2010/12/15/hello-world/#comments</comments>
		<pubDate>Wed, 15 Dec 2010 16:13:42 +0000</pubDate>
		<dc:creator>Xavier Noëlle</dc:creator>
				<category><![CDATA[News]]></category>

		<guid isPermaLink="false">http://rtfblog.wordpress.com/?p=1</guid>
		<description><![CDATA[The RFTBlog is coming soon… Stay tuned and follow us also on our Facebook or Twitter page for the blog launch!<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rtfblog.com&amp;blog=18436446&amp;post=1&amp;subd=rtfblog&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>The RFTBlog is coming soon…</p>
<p>Stay tuned and follow us also on our <a href="http://www.facebook.com/pages/RTFBlog/179046198781364">Facebook</a> or <a href="http://twitter.com/rtfblog">Twitter</a> page for the blog launch!<!-- target="whatever" is EVIL just don't do it. --></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rtfblog.wordpress.com/1/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rtfblog.wordpress.com/1/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/rtfblog.wordpress.com/1/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/rtfblog.wordpress.com/1/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/rtfblog.wordpress.com/1/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/rtfblog.wordpress.com/1/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/rtfblog.wordpress.com/1/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/rtfblog.wordpress.com/1/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/rtfblog.wordpress.com/1/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/rtfblog.wordpress.com/1/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/rtfblog.wordpress.com/1/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/rtfblog.wordpress.com/1/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/rtfblog.wordpress.com/1/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/rtfblog.wordpress.com/1/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rtfblog.com&amp;blog=18436446&amp;post=1&amp;subd=rtfblog&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://rtfblog.com/2010/12/15/hello-world/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/b111270483636e6535de8d04bc54a552?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">xaviernoelle</media:title>
		</media:content>
	</item>
	</channel>
</rss>
