URLにエントリのタイトルを入れるには - WordPressでの実装をのぞきつつ

サーチエンジンはURLに入っている単語も重み付けに使っているそうで、最近はURLにタイトルを入れているサイトが多くなってきています。ただ、日本語の場合URLが極めて長くなってしまうのが困ったところですがVOXやamazonで採用されています。
VOX スイカ割りしたい.html
http://ya-ko.vox.com/library/post/%E3%82%B9%E3%82%A4%E3%82%AB%E5%89%B2%E3%82%8A%E3%81%97%E3%81%9F%E3%81%84.html
amazon スケーラブルWebサイト-Cal-Henderson
http://www.amazon.co.jp/%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%A9%E3%83%96%E3%83%ABWeb%E3%82%B5%E3%82%A4%E3%83%88-Cal-Henderson/dp/4873113113
今回実装をのぞいてみたWordPressは、デフォルトでは ?p=12 みたいなURLになりますが 、[オプション]の[バーマリンク設定](表記は日本語版の場合です)で変更できます。
"日付と記事名に基づく表示"を選択すると .htaccess に
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /blog/ku/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /blog/ku/index.php [L]
</IfModule>
という rewrite rule が追加されます。

WordPressのwp_postテーブル

WordPressでは、エントリのタイトルとURLに使われる名前とを別々に保存することができます。URL用の名前はスラッグと呼ばれています。データはwp_postsテーブルに保存されていて、エントリのタイトルはpost_titleに、スラッグはpost_nameに保存されています。 スラッグを明示的に設定しないときには、エントリのタイトルがスラッグに設定されるようになっています。 http://labs.gmo.jp/blog/ku/2007/07/06/wordpress-slug-implementation という形式でリクエストがくるとWordPressは
SELECT   wp_posts.* FROM wp_posts  WHERE 1=1  AND YEAR(post_date)='2007' AND MONTH(post_date)='7' AND DAYOFMONTH(post_date)='5' AND post_name = 'wordpress-slug-implementation' AND (post_type = 'post')  ORDER BY post_date DESC
こんなSQLを発行しています。post_nameがURLに入っているタイトルと一致するエントリを探しています。 実際にどのインデックスが使われているかEXPLAINで見てみましょう。
+----+-------------+----------+------+-----------------------------------------+-----------+---------+-------+------+-----------------------------+
| id | select_type | table    | type | possible_keys                           | key       | key_len | ref   | rows | Extra                       |
+----+-------------+----------+------+-----------------------------------------+-----------+---------+-------+------+-----------------------------+
|  1 | SIMPLE      | wp_posts | ref  | post_name,type_status_date,post_related | post_name | 202     | const |    3 | Using where; Using filesort |
+----+-------------+----------+------+-----------------------------------------+-----------+---------+-------+------+-----------------------------+
post_nameのインデックスをキーとしてエントリを探していることが分かります。

おんなじタイトルのエントリ問題

URLにタイトルを入れる方式で問題になるのが、おんなじタイトルのエントリを作れないことです。WordPressは、タイトルとURLとなるスラッグとが別々になっているので、同じタイトルのエントリを作ったときには、タイトルは投稿されたオリジナルを使い、URLに使われるスラッグがuniqueになるように、最後に数字をつける方式をとっています。同じタイトルのエントリを投稿すると、あとから投稿したものはwordpress-slug-implementation-2というふうに、最後に数字がついていきます。

この方法だと、今度は何番目まで使ったのかが分からない問題が出てきます。同じタイトルでたくさん投稿されたときに、最後につける数字をいくつにすればいいのかを調べる必要があります。WordPressではテーブルをみる限り、その数字をどこかに保存していたりはしないので、エントリのタイトルが重複するたびに、スラッグにつける数字を1ずつ増やしてテーブルをSELECTして既に使われていないかどうかを調べて、使われていない番号まで探しているのだと予想されます。

スラッグのインデックスっていらないよね

ここで、スラッグの最後につける数字を何番まで使ったかをテーブルに保存しておく、という手もありますが、そもそも数字をつけるのはURLをuniqueにするためなのだから、はじめからエントリのIDをつけるのはどうでしょう。 例として "wordpress slug implementation" というタイトルで4つエントリを投稿したとします。そうするとWordPressでは
wordpress-slug-implementation
wordpress-slug-implementation-1
wordpress-slug-implementation-2
wordpress-slug-implementation-3
の3つのURLが割り当てられます。これを常に最後にエントリIDをつけることにすると(ひとつめのエントリのIDを244としています)
wordpress-slug-implementation-244
wordpress-slug-implementation-245
wordpress-slug-implementation-246
wordpress-slug-implementation-247
のようになります。

こうすると、エントリのURLを決めるときに重複しているかどうかを調べる必要がなくなります。URLの最後にはuniqueになっているのがわかっているエントリIDがついているので、URLが重複することはありません。

さらにいいことに、まじめにスラッグ部分のインデックスをつくって検索する、ということをする必要がなくなります。URLの最後の部分にエントリIDが入っていることが分かっているので、URLの最後の部分を正規表現等で取り出せばはじめからインデックスが張られているエントリIDで検索することができます。スラッグのインデックスを張らなくてよくなったぶん、ディスクスペースを節約できますし(結果としてメモリの消費量が減ってキャッシュのヒット率も上がりそうです)、インデックスの更新がいらなくなる分、無視できる程度でしょうけれどCPUやディスクIOの節約にもなります。

tags

  • MySQL
  • design
  • 「URLにエントリのタイトルを入れるには - WordPressでの実装をのぞきつつ」のはてなブックマーク数
  • 「URLにエントリのタイトルを入れるには - WordPressでの実装をのぞきつつ」deliciousブックマーク数
  • 「URLにエントリのタイトルを入れるには - WordPressでの実装をのぞきつつ」をはてなブックマークに追加
  • save "URLにエントリのタイトルを入れるには - WordPressでの実装をのぞきつつ" to del.icio.us
  • 「URLにエントリのタイトルを入れるには - WordPressでの実装をのぞきつつ」をリアルタイムブログ検索
  • permalink
  • selectの実装探訪
  • AutoPagerize用のXPathをかんたんに作るためのブックマークレット AutoPagerize IDE

comments

TypeKey Enabled
スタイル用のHTMLタグが使えます。
*required

trackbacks

トラックバック元エントリにこのエントリへのリンクがない場合はトラックバックを受け付けません。

http://labs.gmo.jp/mt/mt-tb.cgi/140
©2010 Kentaro Kumagai, GMO Internet Labs., GMO Internet, inc.
bits and bytes
2007 .07. 06 18:34

tagcloud

  • API1
  • C/C++2
  • E4X1
  • FUSE2
  • Firefox18
  • HTML4
  • IE1
  • MySQL1
  • OSX4
  • Opera2
  • PHP4
  • XML1
  • XPCOM4
  • XPath3
  • apache2
  • binary2
  • book1
  • data11
  • debug4
  • design1
  • experiments3
  • extension10
  • google gears1
  • google maps API1
  • greasemonkey3
  • httpd5
  • javascript17
  • linux1
  • logging2
  • mobile3
  • perl4
  • tips4
  • tool11
  • vim2
  • visualization2
  • widget1
  • wii1
  • windows7
  • サービス6
  • 和訳1

Archives

  • 2008.02 (6)
  • 2008.01 (3)
  • 2007.12 (4)
  • 2007.11 (5)
  • 2007.10 (4)
  • 2007.09 (4)
  • 2007.08 (4)
  • 2007.07 (8)
  • 2007.06 (7)
  • 2007.05 (4)
  • 2007.04 (5)
  • 2007.03 (6)
  • 2007.02 (4)
  • 2007.01 (6)

about

  • bits and bytesのXML
  • 「bits and bytes」のCreative Commons
  • Powered by Movable Type
  • イベントと地図 - モグ
  • Use ecto to blog!
  • bits and bytesのはてなブックマーク数
  • bits and bytesをMy Yahoo!に追加
  • Subscribe with Bloglines