{"id":2104,"date":"2010-10-21T07:52:45","date_gmt":"2010-10-21T05:52:45","guid":{"rendered":"http:\/\/code.openark.org\/blog\/?p=2104"},"modified":"2010-10-21T07:52:45","modified_gmt":"2010-10-21T05:52:45","slug":"simple-guideline-for-choosing-appropriate-innodb-primary-keys","status":"publish","type":"post","link":"https:\/\/code.openark.org\/blog\/mysql\/simple-guideline-for-choosing-appropriate-innodb-primary-keys","title":{"rendered":"Simple guideline for choosing appropriate InnoDB PRIMARY KEYs"},"content":{"rendered":"<p>Risking some flames, I&#8217;d like to suggest only two options for choosing <strong>PRIMARY KEY<\/strong>s for InnoDB tables. I suggest they should cover 99% (throwing numbers around) of cases.<\/p>\n<h4>PRIMARY KEY cases<\/h4>\n<ol>\n<li>An integer (SMALLINT \/ INT \/ BIGINT), possibly <strong>AUTO_INCREMENT<\/strong> column.<\/li>\n<li>The combination of two columns on a many-to-many connecting table (e.g. <strong>film_actor<\/strong>, which connects <strong>film<\/strong>s to <strong>actor<\/strong>s), the two columns being the <strong>PRIMARY KEY<\/strong>s of respective data tables. This rule may be extended to 3-way relation tables.<\/li>\n<\/ol>\n<p>A short recap: an InnoDB must have a <strong>PRIMARY KEY<\/strong>. It will pick one if you don&#8217;t offer it. It can pick a really bad <strong>UNIQUE KEY<\/strong> (e.g. <strong>website_url(255)<\/strong>) or make one up using InnoDB internal row ids. If you don&#8217;t have a good candidate, an <strong>AUTO_INCREMENT PRIMARY KEY<\/strong> is probably the easiest way out.<\/p>\n<p>A 2-column combination for a many-to-many connection table is common and viable. The <strong>PRIMARY KEY<\/strong> will not only provide with good join access method, but will also provide with the required <strong>UNIQUE<\/strong> constraint.<\/p>\n<p>An integer-based <strong>PRIMARY KEY<\/strong> will make for more compact &amp; shallow index tree structures, which leads to less I\/O and page reads.<\/p>\n<p>An <strong>AUTO_INCREMENT<\/strong> will allow for ascending <strong>PRIMARY KEY<\/strong> order of <strong>INSERT<\/strong>, which is InnoDB-friendly: index pages will be more utilized, less fragmented.<!--more--><\/p>\n<h4>Exceptions<\/h4>\n<ul>\n<li><strong>You have a partitioned table, e.g. on date range.<\/strong> With partitioned tables, every UNIQUE KEY, including the PRIMARY KEY, must include partitioning columns. In such case you will have to extend the PRIMARY KEY.<\/li>\n<li><strong>The only key on your table is a unique constraint on some column, e.g. UNIQUE KRY (url).<\/strong> On one hand, it seems wasteful to create <em>another<\/em> column (e.g. AUTO_INCREMENT) to use as PRIMARY KEY. On the other hand, I&#8217;ve seen many cases where this kind of PK didn&#8217;t hold up. At some point there was need for another index. Or some method had to be devised for chunking up table data (<a href=\"http:\/\/code.openark.org\/forge\/openark-kit\/oak-chunk-update\">oak-chunk-update<\/a> can do that even with non-integer PKs). I&#8217;m reluctant to use such keys as PRIMARY.<\/li>\n<li>I&#8217;m sure there are others.<\/li>\n<\/ul>\n<h4>Umm&#8230;<\/h4>\n<p>I wrote the draft for this post a while ago. And then came <a href=\"http:\/\/mituzas.lt\/2010\/07\/30\/on-primary-keys\/\">Domas<\/a> and ruined it. <a href=\"http:\/\/bugs.mysql.com\/bug.php?id=55656\">Wait for<\/a> <strong>5.1.52<\/strong>?<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Risking some flames, I&#8217;d like to suggest only two options for choosing PRIMARY KEYs for InnoDB tables. I suggest they should cover 99% (throwing numbers around) of cases. PRIMARY KEY cases An integer (SMALLINT \/ INT \/ BIGINT), possibly AUTO_INCREMENT column. The combination of two columns on a many-to-many connecting table (e.g. film_actor, which connects [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"enabled":false},"version":2}},"categories":[5],"tags":[26,14],"class_list":["post-2104","post","type-post","status-publish","format-standard","hentry","category-mysql","tag-indexing","tag-innodb"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p2bZZp-xW","_links":{"self":[{"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/posts\/2104","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/comments?post=2104"}],"version-history":[{"count":25,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/posts\/2104\/revisions"}],"predecessor-version":[{"id":3056,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/posts\/2104\/revisions\/3056"}],"wp:attachment":[{"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/media?parent=2104"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/categories?post=2104"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/tags?post=2104"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}