<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	
	>
<channel>
	<title>
	Comments on: Denormalized Databases:  A better example	</title>
	<atom:link href="https://www.selikoff.net/2008/11/23/denormalized-databases-a-better-example/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.selikoff.net/2008/11/23/denormalized-databases-a-better-example/</link>
	<description>Java/J2EE Software Development and Technology Discussion Blog</description>
	<lastBuildDate>Tue, 07 Feb 2017 18:40:45 +0000</lastBuildDate>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0</generator>
	<item>
		<title>
		By: Pino		</title>
		<link>https://www.selikoff.net/2008/11/23/denormalized-databases-a-better-example/comment-page-1/#comment-186613</link>

		<dc:creator><![CDATA[Pino]]></dc:creator>
		<pubDate>Tue, 07 Feb 2017 18:40:45 +0000</pubDate>
		<guid isPermaLink="false">http://www.selikoff.net/blog/?p=622#comment-186613</guid>

					<description><![CDATA[&quot;SQL doesn’t support unlimited-recursive queries of this nature&quot;

That&#039;s true for parent-linked trees.

One denormalization to work around this is your user-to-widget table. But that can grow fairly quickly when several users are given privileges over the head of a large category tree.

Another denormalization is to cache of the category tree&#039;s preorder traversal as a &quot;nested set&quot; model. With a nested set, you can quickly look up all parents of a node or all descendants of a node. Then to see if a user has privileges on a node or any of its ancestors, you can do something like this to find all ancestors of category 1233 where Chester has privileges:

SELECT couter.catid, p.privs
FROM users u
INNER JOIN user_subcat_privs p ON p.userid = u.userid
INNER JOIN subcats couter ON p.catid = couter.catid
INNER JOIN subcats cinner
ON (couter.lft &#060;= cinner.lft AND cinner.lft &#060;= couter.rgt)
WHERE users.username = ? AND cinner.catid = ?
--args: (&#039;Chester&#039;, 1233)

This is O(n) for a node of depth n, as cinner.lft will be between couter.lft and couter.rgt only for a particular category&#039;s ancestors. It doesn&#039;t grow as quickly as more users are added or when a user&#039;s privileges on a fairly large category are changed.

Nested sets can be regenerated periodically, or they can even be updated in place.
http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/]]></description>
			<content:encoded><![CDATA[<p>&#8220;SQL doesn’t support unlimited-recursive queries of this nature&#8221;</p>
<p>That&#8217;s true for parent-linked trees.</p>
<p>One denormalization to work around this is your user-to-widget table. But that can grow fairly quickly when several users are given privileges over the head of a large category tree.</p>
<p>Another denormalization is to cache of the category tree&#8217;s preorder traversal as a &#8220;nested set&#8221; model. With a nested set, you can quickly look up all parents of a node or all descendants of a node. Then to see if a user has privileges on a node or any of its ancestors, you can do something like this to find all ancestors of category 1233 where Chester has privileges:</p>
<p>SELECT couter.catid, p.privs<br />
FROM users u<br />
INNER JOIN user_subcat_privs p ON p.userid = u.userid<br />
INNER JOIN subcats couter ON p.catid = couter.catid<br />
INNER JOIN subcats cinner<br />
ON (couter.lft &lt;= cinner.lft AND cinner.lft &lt;= couter.rgt)<br />
WHERE users.username = ? AND cinner.catid = ?<br />
&#8211;args: (&#039;Chester&#039;, 1233)</p>
<p>This is O(n) for a node of depth n, as cinner.lft will be between couter.lft and couter.rgt only for a particular category&#039;s ancestors. It doesn&#039;t grow as quickly as more users are added or when a user&#039;s privileges on a fairly large category are changed.</p>
<p>Nested sets can be regenerated periodically, or they can even be updated in place.<br />
<a href="http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/" rel="nofollow ugc">http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/</a></p>
]]></content:encoded>
		
			</item>
		<item>
		<title>
		By: Excel Tutorials		</title>
		<link>https://www.selikoff.net/2008/11/23/denormalized-databases-a-better-example/comment-page-1/#comment-2351</link>

		<dc:creator><![CDATA[Excel Tutorials]]></dc:creator>
		<pubDate>Wed, 21 Apr 2010 04:18:43 +0000</pubDate>
		<guid isPermaLink="false">http://www.selikoff.net/blog/?p=622#comment-2351</guid>

					<description><![CDATA[You shouldn&#039;t assume that you know how any particular database engine will perform a given task. They will all be different. For example, some may allocate space to empty fields, some may not; joins may sometimes be performed with table accesses and sometimes with index lookups. Frequently used small tables may be kept in memory and be very quick to access. The advantage of a normalised design is as a consistent start point from which to optimise for performance, if that is what&#039;s needed. Optimisation may be by tuning the database, creating indexes or denormalising as appropriate.]]></description>
			<content:encoded><![CDATA[<p>You shouldn&#8217;t assume that you know how any particular database engine will perform a given task. They will all be different. For example, some may allocate space to empty fields, some may not; joins may sometimes be performed with table accesses and sometimes with index lookups. Frequently used small tables may be kept in memory and be very quick to access. The advantage of a normalised design is as a consistent start point from which to optimise for performance, if that is what&#8217;s needed. Optimisation may be by tuning the database, creating indexes or denormalising as appropriate.</p>
]]></content:encoded>
		
			</item>
		<item>
		<title>
		By: Yma		</title>
		<link>https://www.selikoff.net/2008/11/23/denormalized-databases-a-better-example/comment-page-1/#comment-1775</link>

		<dc:creator><![CDATA[Yma]]></dc:creator>
		<pubDate>Tue, 21 Jul 2009 16:08:28 +0000</pubDate>
		<guid isPermaLink="false">http://www.selikoff.net/blog/?p=622#comment-1775</guid>

					<description><![CDATA[Denormalization is beneficial especially if you have a normalized hierarchical table.An example could be parts having subparts resulting in a hierarchy of multiple levels. I did a time check on with an SQL query on this kind of a table(with 3 levels ) and the denormalized table gave a substantial performance improvement (with respect to time)]]></description>
			<content:encoded><![CDATA[<p>Denormalization is beneficial especially if you have a normalized hierarchical table.An example could be parts having subparts resulting in a hierarchy of multiple levels. I did a time check on with an SQL query on this kind of a table(with 3 levels ) and the denormalized table gave a substantial performance improvement (with respect to time)</p>
]]></content:encoded>
		
			</item>
		<item>
		<title>
		By: Michael Ernest		</title>
		<link>https://www.selikoff.net/2008/11/23/denormalized-databases-a-better-example/comment-page-1/#comment-597</link>

		<dc:creator><![CDATA[Michael Ernest]]></dc:creator>
		<pubDate>Sun, 23 Nov 2008 22:20:58 +0000</pubDate>
		<guid isPermaLink="false">http://www.selikoff.net/blog/?p=622#comment-597</guid>

					<description><![CDATA[I wanted to chime in on the last article too, but for lack of time I couldn&#039;t finish my point, then lost what I had written to a cache flush. Oy.

My two cents on this one: delete this apology! Simple examples are meant to be taken apart, but for the sake of clarifying the problem, not criticizing the writer. The only nitpick that is worth reading to the end is a better example! If someon truly didn&#039;t get what you were saying because of your example, that&#039;s one thing.

As I see it, whiteboard examples are limiting in proportion to how literally it is understood -- and how quickly the reader would hope to apply it, rather than mediate on the meaning. If I&#039;ve learned anything from my almost-15 years in technical training, it&#039;s that people don&#039;t want to think if they don&#039;t have to, they want to plug in. Unless you&#039;re offering that service, stick to examples that demonstrate your point without proving it. Let the impatient reader meet you halfway. If they don&#039;t want to do even that, don&#039;t worry about it! You do well enough to put your points out there for free.

Keep &#039;em coming, Scott!]]></description>
			<content:encoded><![CDATA[<p>I wanted to chime in on the last article too, but for lack of time I couldn&#8217;t finish my point, then lost what I had written to a cache flush. Oy.</p>
<p>My two cents on this one: delete this apology! Simple examples are meant to be taken apart, but for the sake of clarifying the problem, not criticizing the writer. The only nitpick that is worth reading to the end is a better example! If someon truly didn&#8217;t get what you were saying because of your example, that&#8217;s one thing.</p>
<p>As I see it, whiteboard examples are limiting in proportion to how literally it is understood &#8212; and how quickly the reader would hope to apply it, rather than mediate on the meaning. If I&#8217;ve learned anything from my almost-15 years in technical training, it&#8217;s that people don&#8217;t want to think if they don&#8217;t have to, they want to plug in. Unless you&#8217;re offering that service, stick to examples that demonstrate your point without proving it. Let the impatient reader meet you halfway. If they don&#8217;t want to do even that, don&#8217;t worry about it! You do well enough to put your points out there for free.</p>
<p>Keep &#8217;em coming, Scott!</p>
]]></content:encoded>
		
			</item>
	</channel>
</rss>
