<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss'><id>tag:blogger.com,1999:blog-7853030439906136597</id><updated>2009-02-21T02:40:06.617-08:00</updated><title type='text'>Databases from Inside</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://john-database.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7853030439906136597/posts/default'/><link rel='alternate' type='text/html' href='http://john-database.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>John</name><uri>http://www.blogger.com/profile/01569508111199787709</uri><email>noreply@blogger.com</email></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>3</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7853030439906136597.post-4865126044718213818</id><published>2008-03-04T17:23:00.000-08:00</published><updated>2008-03-04T17:25:52.961-08:00</updated><title type='text'>10+ things you should do before building a custom Access database</title><content type='html'>&lt;p&gt;Whether you take on freelance work or you support your organization’s IT needs by developing custom database solutions, you must build an efficient, easy-to-use database if you plan to stay employed. Like most things, there’s a right and a wrong way. You might not get credit for doing things right, but you’ll certainly hear about it if you do things wrong.&lt;/p&gt; &lt;p&gt;The road to the right database starts well before you start building tables. There are a number of things you can do &lt;em&gt;before&lt;/em&gt; you build a database to make sure that the development process goes smoothly and that your custom database fits the organization’s purpose and goals. The following tips are aimed as Access users, but most of them apply to just about any custom database.&lt;/p&gt;  &lt;h3&gt;#1: Make nice&lt;/h3&gt; &lt;p&gt;You’ll get nowhere without the support and guidance of two specific groups of people:&lt;/p&gt; &lt;ul type="disc"&gt;&lt;li&gt;Those who      update the data. These people know what’s needed to get the job done.&lt;/li&gt;&lt;li&gt;Those      who use the information. These people know the goals for the database and      the business at large.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;In a small company, one person might fill both positions, although they have different needs. However, that person’s experiences with the data are valid. It’s your job to find solutions that satisfy everyone, within reason.&lt;/p&gt; &lt;h3&gt;#2: Bend but don’t break&lt;/h3&gt; &lt;p&gt;Being &lt;em&gt;just&lt;/em&gt; a developer won’t get the job done. Sometimes, you must be a diplomat. I recommend that you practice the art of persuasion: “Let me show you something…” will serve you better than “That can’t be done.” This may require you to think fast on your feet. Of course, “Let me work up an example” can always buy a little time.&lt;/p&gt; &lt;h3&gt;#3: Actually review their specs&lt;/h3&gt; &lt;p&gt;Sometimes, you get lucky and someone in-house supplies a list of specifications. If that happens, it’s information worth keeping, so don’t be too eager to trash the list. Working with those original specs will save you some time and might keep you from stepping on someone’s toes — never a good idea if you can help it.&lt;/p&gt; &lt;h3&gt;#4: Compare the specs to the working environment&lt;/h3&gt; &lt;p&gt;Most Access databases have just a few users, but Access can handle numerous users. You probably won’t build an interactive intranet database the same way you’d build the solution for a single user. Access seldom fails to meet the demands if you develop for multiple users from the beginning.&lt;/p&gt; &lt;h3&gt;#5: How many keys are there to the front door?&lt;/h3&gt; &lt;p&gt;Keeping hackers out of your intranet or Web-based database is much more complex than using Access’ workgroup security. In fact, if you need this article and you’ve taken on a Web-based database project, you might have bitten off more than you can chew — good luck! Access is certainly up to the challenge, but the truth is, most developers aren’t. That’s why IT professionals scoff at Access. The sad truth is, many developers don’t understand the Web. If you’re one of them, don’t take on a Web project hoping to learn on the job. You and your client will pay too high a price.&lt;/p&gt; &lt;h3&gt;#6: Do the work&lt;/h3&gt; &lt;p&gt;Sit down with the people who do the work and learn the process:&lt;/p&gt; &lt;ul type="disc"&gt;&lt;li&gt;Review      all paper forms in the current process.&lt;/li&gt;&lt;li&gt;How      much data — both records and fields — will the database store?&lt;/li&gt;&lt;li&gt;How      much searching and sorting will the users require?&lt;/li&gt;&lt;li&gt;Where      does the data come from? Will the system need to accommodate foreign data?&lt;/li&gt;&lt;li&gt;Will      the system export data to foreign formats?&lt;/li&gt;&lt;li&gt;Review      the current reports and analysis. Talk with the people who use them, for      insight.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;In short, follow the data from beginning to end. There’s no substitute for knowing the data and the current motivations that push that data from collection to final form.&lt;/p&gt; &lt;h3&gt;#7: Re-evaluate&lt;/h3&gt; &lt;p&gt;Once you’re familiar with the specs and environment, you might have to shoot yourself in the foot. Access just might not be the best solution for your client. A more powerful system, such as SQL Server 2005 Express Edition, might be a better choice. Or Access might be just part of the solution. For instance, InfoPath’s XML-based forms or .NET forms might be more efficient than Access forms, especially if you’re publishing data to an intranet or to the Internet. Certainly, Excel’s analytical tools are superior to those Access provides. Don’t try to stuff the entire works into an Access-or-bust solution.&lt;/p&gt; &lt;h3&gt;#8: Recommend the best route — not the easiest one&lt;/h3&gt; &lt;p&gt;Don’t be afraid to suggest a major overhaul if you’re upgrading a legacy database. Neither the latest and greatest version of Access nor more expensive hardware will resolve performance issues that stem from bad design.&lt;/p&gt; &lt;h3&gt;#9: Improve the process&lt;/h3&gt; &lt;p&gt;Work with the end users to improve the manual process if there’s room for improvement, and there usually is. It’s a mistake to computerize the existing workflow until it’s the best it can be. Software alone won’t improve a bad routine — it’ll just change the problems.&lt;/p&gt; &lt;h3&gt;#10: Define and redefine&lt;/h3&gt; &lt;p&gt;Once you’ve gathered all your facts, compose a mission statement for the application. This might require one to several paragraphs. I’m not talking about a new set of specifications. Rather, give your client a realistic review of their needs versus reality. You’re simply restating the database’s purposes, but with the benefit of your insight into the workflow and organization’s needs.&lt;/p&gt; &lt;h3&gt;#11: How’s that for quick response?&lt;/h3&gt; &lt;p&gt;Once you believe you have a good feel for the client’s needs and the database’s purposes, create a series of mock-up forms to show the client. You’ll get a few oohs and ahhhs, but listen to the souls brave enough to say, “But wait…” Their insights may be valid and could save you some trouble down the road. On the other hand, this is where #2 can come in handy. Sometimes, people just can’t conceive of doing something any way but the way they know.&lt;/p&gt; &lt;p&gt;You can use graphics software to draw and print the forms or use Access — it’s a great rapid applications development (RAD) tool. And you can really impress your clients by actually using their data. Sometimes, a quick run at normalizing the data can help the mock-up process. It’s not strictly necessary, but it may show you some holes you might otherwise miss.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7853030439906136597-4865126044718213818?l=john-database.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://john-database.blogspot.com/feeds/4865126044718213818/comments/default' title='Objavi komentare'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7853030439906136597&amp;postID=4865126044718213818' title='0 komentara'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7853030439906136597/posts/default/4865126044718213818'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7853030439906136597/posts/default/4865126044718213818'/><link rel='alternate' type='text/html' href='http://john-database.blogspot.com/2008/03/10-things-you-should-do-before-building.html' title='10+ things you should do before building a custom Access database'/><author><name>John</name><uri>http://www.blogger.com/profile/01569508111199787709</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00860676824284449958'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7853030439906136597.post-5521321151829768674</id><published>2008-02-24T11:05:00.000-08:00</published><updated>2008-02-24T11:06:44.369-08:00</updated><title type='text'>How to Backup SQL Database - 4 Top Methods</title><content type='html'>&lt;p&gt;If you have installed a blog, forum or content management system (CMS) such as Joomla on your server you will have installed a mySQL database. One day without warning your server may crash and you’ll lose all your files. This is why it is important to create a backup of database and files.&lt;/p&gt; &lt;p&gt;If your web site only contains html files it’s very easy to restore them because they are stored on your computer. You simply need to upload them to the server.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Methods of backing up your SQL database&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;1. Web hosting providers&lt;/strong&gt; - Most web hosting providers backup all files on their server. My server gets backed up daily, weekly and monthly. Check with your web host to see how often they do backups.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;2. Backup software&lt;/strong&gt; for your forum, blog or cms&lt;/p&gt; &lt;p&gt;Most CMS web sites that use databases have their own backup system software. e.g., &lt;/p&gt; &lt;p&gt;&lt;strong&gt;a) WordPress&lt;/strong&gt; has a plugin (http://www.ilfilosofo.com/blog/wp-db-backup/) where you can select how you want the backup to be delivered:&lt;/p&gt; &lt;p&gt;* Save to server : this will create a file in /wp-content/backup-*/ for you to retrieve later&lt;br /&gt;* Download to your computer : this will send the backup file to your browser to be downloaded&lt;br /&gt;* Email : this will email the backup file to the address you specify&lt;/p&gt; &lt;p&gt;&lt;strong&gt;b) Joomla&lt;/strong&gt; has an extension called JoomlaPack (http://www.joomlapack.net/). It’s a component that creates a backup of your whole site (files and database) in the form of a single archive. In order to help you restore this, it also adds an installer. All you have to do to restore your backup is follow the regular Joomla! installation procedure: unpack the archive, upload files, point your browser to the installation script, follow the installation screens and you’re ready.&lt;br /&gt;&lt;strong&gt;&lt;br /&gt;c) Simple Machines Forum&lt;/strong&gt; (SMF) allows you to create a backup of the forum database within the admin panel.&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;3. Cpanel backup&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Use the MySQL Database Wizard to download a zipped copy of your entire site or parts of it onto your computer.&lt;/p&gt; &lt;p&gt;The following are backed up and included in a zip file:&lt;/p&gt; &lt;p&gt;* Home Directory&lt;br /&gt;* MySQL Databases&lt;br /&gt;* Email forwarders configuration&lt;br /&gt;* Email filters configuration&lt;/p&gt; &lt;p&gt;To access the MySQL Database Wizard login to:&lt;/p&gt; &lt;p&gt;www.domain.com/cpanel&lt;br /&gt;files&lt;br /&gt;backup wizard&lt;br /&gt;save the files to your local drive&lt;/p&gt; &lt;p&gt;&lt;strong&gt;4. phpMyAdmin&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Have you ever lost all your computer files because you didn’t back them up? &lt;/strong&gt;&lt;/p&gt; &lt;p&gt;It’s a sickening feeling when you can’t restore thousands of files collected over several years of work. The same thing can happen to your forum, blog or CMS web site that uses a mySQL database to store information. One of the easiest and most full proof backup methods is to use phpMyAdmin.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;How to use phpMyAdmin&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Go to cPanel-&gt;mySQL databases-&gt;phpMyAdmin and choose your database.&lt;br /&gt;Click on the Export link.&lt;br /&gt;Choose Select All to select all the tables.&lt;br /&gt;Select “SQL”-&gt;for output format.&lt;br /&gt;Check “save as file”&lt;br /&gt;Select gzipped and hit Go to download the backup file.&lt;br /&gt;Save it to a folder labeled “backupFeb08″ so you know when you created the last backup.&lt;/p&gt; &lt;p&gt;Create a backup the first of every month.&lt;br /&gt;&lt;strong&gt;&lt;br /&gt;How to restore a backup of a mySQL database&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Click the SQL tab&lt;br /&gt;On the “SQL” page, unclick “show this query here again”&lt;br /&gt;Browse to the backup of the database on your computer&lt;br /&gt;Click Go.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7853030439906136597-5521321151829768674?l=john-database.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://john-database.blogspot.com/feeds/5521321151829768674/comments/default' title='Objavi komentare'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7853030439906136597&amp;postID=5521321151829768674' title='0 komentara'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7853030439906136597/posts/default/5521321151829768674'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7853030439906136597/posts/default/5521321151829768674'/><link rel='alternate' type='text/html' href='http://john-database.blogspot.com/2008/02/how-to-backup-sql-database-4-top.html' title='How to Backup SQL Database - 4 Top Methods'/><author><name>John</name><uri>http://www.blogger.com/profile/01569508111199787709</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00860676824284449958'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7853030439906136597.post-1088706501199086656</id><published>2008-02-24T11:02:00.000-08:00</published><updated>2008-02-24T11:04:45.742-08:00</updated><title type='text'>When not to normalize your database</title><content type='html'>&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Database_normalization"&gt;&lt;/a&gt;Database normalization is a formal process of designing your database to eliminate redundant data, utilize space efficiently and reduce update errors. Anyone who has ever taken a database class has it drummed into their heads that a normalized database is the only way to go. This is true for the most part . However there are certain scenarios where the benefits of database normalization are outweighed by its costs. Two of these scenarios are described below. &lt;/p&gt; &lt;h4&gt;Immutable Data and Append-Only Scenarios&lt;/h4&gt; &lt;p&gt;Pat Helland, an enterprise architect at Microsoft who just rejoined the company after a two year stint at Amazon, has a blog post entitled Normalization is for Sissies where he presents his slides from an internal Microsoft gathering on database topics. In his presentation, Pat argues that database normalization is unnecessary in situations where we are storing immutable data such as financial transactions or a particular day's price list. &lt;/p&gt; &lt;h4&gt;When Multiple Joins are Needed to Produce a Commonly Accessed View&lt;/h4&gt; &lt;p&gt;The biggest problem with normalization is that you end up with multiple tables representing what is conceptually a single item. For example, consider this normalized set of tables which represent a user profile on a typical social networking site. &lt;/p&gt; &lt;table border="1"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;th colspan="9"&gt;user table&lt;/th&gt;&lt;/tr&gt; &lt;tr&gt; &lt;/tr&gt;&lt;tr&gt; &lt;th&gt;user_id&lt;/th&gt; &lt;th&gt;first_name&lt;/th&gt; &lt;th&gt;last_name&lt;/th&gt; &lt;th&gt;sex&lt;/th&gt; &lt;th&gt;hometown&lt;/th&gt; &lt;th&gt;relationship_status&lt;/th&gt; &lt;th&gt;interested_in  &lt;/th&gt;&lt;th&gt;religious_views&lt;/th&gt; &lt;th&gt;political_views&lt;/th&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;12345&lt;/td&gt; &lt;td&gt;John&lt;/td&gt; &lt;td&gt;Doe&lt;/td&gt; &lt;td&gt;Male&lt;/td&gt; &lt;td&gt;Atlanta, GA&lt;/td&gt; &lt;td&gt;married&lt;/td&gt; &lt;td&gt;women&lt;/td&gt; &lt;td&gt;(null)&lt;/td&gt; &lt;td&gt;(null)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;table border="1"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;th colspan="3"&gt;user_affiliations table&lt;/th&gt;&lt;/tr&gt; &lt;tr&gt; &lt;/tr&gt;&lt;tr&gt; &lt;th&gt;user_id (foreign_key)&lt;/th&gt; &lt;th&gt;affiliation_id (foreign key)&lt;/th&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;12345&lt;/td&gt; &lt;td&gt;42&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;12345&lt;/td&gt; &lt;td&gt;598&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;table border="1"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;th colspan="3"&gt;affiliations table&lt;/th&gt;&lt;/tr&gt; &lt;tr&gt; &lt;/tr&gt;&lt;tr&gt; &lt;th&gt;affiliation_id&lt;/th&gt; &lt;th&gt;description&lt;/th&gt; &lt;th&gt;member_count&lt;/th&gt; &lt;/tr&gt;&lt;tr&gt; &lt;td&gt;42&lt;/td&gt; &lt;td&gt;Microsoft&lt;/td&gt; &lt;td&gt;18,656&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;598&lt;/td&gt; &lt;td&gt;Georgia Tech&lt;/td&gt; &lt;td&gt;23,488&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;table border="1"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;th colspan="3"&gt;user_phone_numbers table&lt;/th&gt;&lt;/tr&gt; &lt;tr&gt; &lt;/tr&gt;&lt;tr&gt; &lt;th&gt;user_id (foreign_key)&lt;/th&gt; &lt;th&gt;phone_number &lt;/th&gt; &lt;th&gt;phone_type&lt;/th&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;12345&lt;/td&gt; &lt;td&gt;425-555-1203&lt;/td&gt; &lt;td&gt;Home&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;12345&lt;/td&gt; &lt;td&gt;425-555-6161&lt;/td&gt; &lt;td&gt;Work&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;12345&lt;/td&gt; &lt;td&gt;206-555-0932&lt;/td&gt; &lt;td&gt;Cell&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;table border="1"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;th colspan="3"&gt;user_screen_names table&lt;/th&gt;&lt;/tr&gt; &lt;tr&gt; &lt;/tr&gt;&lt;tr&gt; &lt;th&gt;user_id (foreign_key)&lt;/th&gt; &lt;th&gt;screen_name &lt;/th&gt; &lt;th&gt;im_service&lt;/th&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;12345&lt;/td&gt; &lt;td&gt;geeknproud@example.com&lt;/td&gt; &lt;td&gt;AIM&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;12345&lt;/td&gt; &lt;td&gt;voip4life@example.org&lt;/td&gt; &lt;td&gt;Skype&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;table border="1"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;th colspan="3"&gt;user_work_history table&lt;/th&gt;&lt;/tr&gt; &lt;tr&gt; &lt;/tr&gt;&lt;tr&gt; &lt;th&gt;user_id (foreign_key)&lt;/th&gt; &lt;th&gt;company_affiliation_id (foreign key)&lt;/th&gt; &lt;th&gt;company_name&lt;/th&gt; &lt;th&gt;job_title&lt;/th&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;12345&lt;/td&gt; &lt;td&gt;42&lt;/td&gt; &lt;td&gt;Microsoft&lt;/td&gt; &lt;td&gt;Program Manager&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;12345&lt;/td&gt; &lt;td&gt;78&lt;/td&gt; &lt;td&gt;i2 Technologies&lt;/td&gt; &lt;td&gt;Quality Assurance Engineer&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;This is the kind of information you see on the average profile on Facebook. With the above design, it takes six SQL Join operations to access and display the information about a single user. This makes rendering the profile page a fairly database intensive operation which is compounded by the fact that profile pages are the most popular pages on social networking sites. &lt;/p&gt; &lt;p&gt;The simplest way to fix this problem is to denormalize the database. Instead of having tables for the user’s affiliations, phone numbers, IM addresses and so on, we can just place them in the &lt;code&gt;user&lt;/code&gt; table as columns. The drawback with this approach is that there is now more wasted space (e.g. lots of college students people will have &lt;code&gt;null&lt;/code&gt; for their work_phone)  and perhaps some redundant information (e.g. if we copy over the description of each affiliation into an affiliation_name column for each user to prevent having to do a join with the affiliations table). However given the very low costs of storage versus the improved performance characteristics of querying a single table and not having to deal with SQL statements that operate across six tables for every operation. This is a small price to pay. &lt;/p&gt; &lt;p&gt;As Joe Gregorio mentions in his blog post about the emergence of megadata, a lot of the large Web companies such as Google, eBay and Amazon are heavily into denormalizing their databases as well as eschewing transactions when updating these databases to improve their scalability. &lt;/p&gt; &lt;p&gt;Maybe normalization is for sissies…&lt;/p&gt; &lt;p&gt;&lt;b&gt;UPDATE&lt;/b&gt;: Someone pointed out in the comments that denormalizing the affiliations table into user's table would mean the member_count would have to updated in thousands of user's rows when a new member was added to the group. This is obviously not the intent of denormalization for performance reasons since it replaces a bad problem with a worse one. Since an affiliation is a distinct concept from a user, it makes sense for it to have it's own table. Replicating the names of the groups a user is affiliated with in the user table is a good performance optimization although it does mean that the name has to be fixed up in thousands of tables if it ever changes. Since this is likely to happen very rarely, this is probably acceptable especially if we schedule renames to be done by a cron job during offpeak ours On the other hand, replicating the member count is just asking for trouble.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;UPDATE 2: &lt;/b&gt;Lots of great comments here and on reddit indicate that I should have put more context around this post. Database denormalization is the kind of performance optimization that should be carried out as a last resort after trying things like creating database indexes, using SQL views and implementing application specific in-memory caching. However if you hit massive scale and are dealing with millions of queries a day across hundreds of millions to billions of records or have decided to go with database partitioning/sharding then you will likely end up resorting to denormalization. A real-world example of this is the Flickr database back-end whose details are described in Tim O'Reilly's Database War Stories #3: Flickr which contains the following quotes  &lt;/p&gt;&lt;blockquote&gt; &lt;i&gt;tags are an interesting one. lots of the 'web 2.0' feature set doesn't fit well with traditional normalised db schema design. denormalization (or heavy caching) is the only way to generate a tag cloud in milliseconds for hundereds of millions of tags. you can cache stuff that's slow to generate, but if it's so expensive to generate that you can't ever regenerate that view without pegging a whole database server then it's not going to work (or you need dedicated servers to generate those views - some of our data views are calculated offline by dedicated processing clusters which save the results into mysql). &lt;br /&gt;&lt;br /&gt;federating data also means denormalization is necessary - if we cut up data by user, where do we store data which relates to two users (such as a comment by one user on another user's photo). if we want to fetch it in the context of both user's, then we need to store it in both shards, or scan every shard for one of the views (which doesn't scale). we store alot of data twice, but then theres the issue of it going out of sync. we can avoid this to some extent with two-step transactions (open transaction 1, write commands, open transaction 2, write commands, commit 1st transaction if all is well, commit 2nd transaction if 1st commited) but there still a chance for failure when a box goes down during the 1st commit.&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#ff0000;"&gt;we need new tools to check data consistency across multiple shards, move data around shards and so on&lt;/span&gt; - a lot of the flickr code infrastructure deals with ensuring data is consistent and well balanced and finding and repairing it when it's not."&lt;/i&gt;&lt;/blockquote&gt; &lt;p&gt;The part highlighted in red is also important to consider. Denormalization means that you you are now likely to deal with data inconsistencies because you are storing redundant copies of data and may not be able to update all copies of a column value simultaneously  when it is changed for a variety of reasons. Having tools in your infrastructure to support fixing up data of this sort then become very important. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7853030439906136597-1088706501199086656?l=john-database.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://john-database.blogspot.com/feeds/1088706501199086656/comments/default' title='Objavi komentare'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7853030439906136597&amp;postID=1088706501199086656' title='0 komentara'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7853030439906136597/posts/default/1088706501199086656'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7853030439906136597/posts/default/1088706501199086656'/><link rel='alternate' type='text/html' href='http://john-database.blogspot.com/2008/02/when-not-to-normalize-your-database.html' title='When not to normalize your database'/><author><name>John</name><uri>http://www.blogger.com/profile/01569508111199787709</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00860676824284449958'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry></feed>