[wp-trac] [WordPress Trac] #2699: Make option_name index unique

WordPress Trac wp-trac at lists.automattic.com
Sun Oct 4 07:55:54 UTC 2009


#2699: Make option_name index unique
------------------------------+---------------------------------------------
 Reporter:  johnjosephbachir  |        Owner:  ryan    
     Type:  task (blessed)    |       Status:  reopened
 Priority:  high              |    Milestone:  2.9     
Component:  Optimization      |      Version:  2.8     
 Severity:  normal            |   Resolution:          
 Keywords:                    |  
------------------------------+---------------------------------------------

Comment(by johnjosephbachir):

 Hey folks -- cool to see my ticket resurrected after 3 years :-)

 Replying to [comment:25 ryan]:
 > Some WPMU installs use InnoDB for the options table.  Having a varchar
 as the primary key isn't the best for InnoDB since it prefers small,
 sequential primary keys.  Should we make option_id primary and option_name
 unique?

 That's true -- it's a pretty bad idea to make an innodb primary key non-
 numeric or non-sequential, and here we are doing both.

 Having a primary key on option_id, and then a separate unique key covering
 whatever columns we like, will provide the same performance benefits, with
 a slight increase in disk space used by that table and its indexes (but
 maybe not compared to what we had before-- I'd have to think a little
 harder to be sure). At any rate, it's a good design.

 in r11883:

 {{{
 #!sql
 PRIMARY KEY  (option_name),
 KEY option_id (option_id)
 }}}

 Best for InnoDB (and probably best or equivalent in myisam as well:)

 {{{
 #!sql
 PRIMARY KEY  (option_id),
 UNIQUE option_name (option_name)
 }}}

 And while we're at it, having the unique key cover all of the columns in
 popular queries would allow for innodb to not have to go back to the
 primary data store to get the info, and only stay in the index, cutting
 down on a spindle access or two, per query.

 Because the most common query on that table by far is this (found in
 functions.php around line 347):

 {{{
 #!sql
 SELECT option_value FROM $wpdb->options WHERE option_name = '$setting'
 LIMIT 1
 }}}

 We could get a big performance win with this index:

 {{{
 #!sql
 PRIMARY KEY  (option_id),
 UNIQUE option_name (option_name, option_value )
 }}}

 And that's what I recommend as the least obtrusive optimization. (assuming
 we do still want to enforce uniqueness of option_name at the DBMS layer--
 otherwise just make it a straight `INDEX`)

 Now, something to consider is that
  1. option_id is currently a `bigint`, which means it is 8 bytes. This
 restricts the number of rows in that table to (wait for it…)
 '''18,446,744,073,709,551,615'''
  1. the bigger the column on which a primary key is made, the worse the
 performance (both for space and time complexity), ''especially'' if it is
 bigger than 4 bytes (`int`).
  1. so, assuming that we are okay with that table holding only the number
 of rows allowed by `int` (4,294,967,295 -- yes, that's 4.3 billion), it
 would be beneficial to make option_id an `int`

 But-- that's the case with all the tables in the system that won't need to
 hold more than 4.2 billion entries. I can make a separate ticket for that
 if you guys think that's an idea that should be discussed further.

-- 
Ticket URL: <http://core.trac.wordpress.org/ticket/2699#comment:27>
WordPress Trac <http://core.trac.wordpress.org/>
WordPress blogging software


More information about the wp-trac mailing list