MySQLの複合主キーテーブル検索時の速度比較

MySQL の複合主キーテーブルのレコードを何件かピックアップして主キー検索したい機会があったので、いくつかのパターンの SQL で検索してパフォーマンス比較をしてみました。

実験の内容

  • それぞれ適当にピックアップした15レコードを1クエリで検索する
  • 実行時間は同じクエリを5回実行したときの最小と最大の時間を計測
  • レコードは適当に100,000件投入

実験環境

  • Ubuntu 13.10 (on Vagrant)
  • MySQL 5.5.37
  • InnoDB

使用したテーブル

CREATE TABLE `myTable` (
  `player_id` int(11) NOT NULL,
  `id` int(11) NOT NULL,
  `body` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`player_id`,`id`)
) ENGINE=InnoDB;

各検索方法の実行時間とインデックス使用状況

1. OR検索の場合

SQL例

SELECT * FROM `myTable`
WHERE  (`player_id` = 50 AND `id` = 4856)
  OR (`player_id` = 61 AND `id` = 4274);

※実験時は15個のORを繋げて検索しましたが長くなるのでここでは省略しています。

実行時間

1.2ms ~ 1.5ms

EXPLAIN結果

id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE myTable range PRIMARY PRIMARY 8 NULL 15 Using where

2. UNION ALL検索の場合

SQL例

SELECT * FROM `myTable` WHERE (`player_id` = 50 AND `id` = 4856)
UNION ALL
SELECT * FROM `myTable` WHERE (`player_id` = 61 AND `id` = 4274);

実行時間

1.5ms ~ 2.0ms

EXPLAIN結果

id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY myTable const PRIMARY PRIMARY 8 const,const 1
2 UNION myTable const PRIMARY PRIMARY 8 const,const 1
15 UNION myTable const PRIMARY PRIMARY 8 const,const 1
NULL UNION RESULT ALL NULL NULL NULL NULL NULL

3. WHERE IN の複合カラム指定による検索の場合

SQL例

SELECT * FROM `myTable`
WHERE (player_id, id) IN ((50, 4856),(61, 4274));

実行時間

40.9ms ~ 49.7ms

EXPLAIN結果

id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE myTable ALL NULL NULL NULL NULL 100714 Using where

コメント

最も高速なのは普通に OR で繋げる検索でした。range スキャンになるんですね。次点で UNION ALL 検索。ちなみに ALL 無しの UNION に変えてもほぼ同じ速度でした。

そして最も遅かったのは WHERE IN 検索でした。IN 句に指定する件数が多いとオプティマイザはフルスキャンを選択するため大幅に遅い結果になりました。

Slackへのプルリクエスト通知に対応しました

以前ひそかに Bitbucket 上で Pull Request 作成やコメントをしたとき、任意の Chatwork グループチャットに通知するツール を作ったのですが、Slack チャットへの投稿にも対応しました。

上の画像が実際に Slack に通知されている場面のキャプチャ画像です。

最初は Slack 標準の外部サービス連携(Integration)でやればいいじゃん、と思ったのですが、世の中そんなに甘くなく、現状だと Bitbucket のプルリクエストの通知をサポートしていないようなのでそれを行うための補助ツールになります。

リポジトリは以下になります。

以下、つらつらと概要を書いていきます。
README.md に書いている内容とほぼ同じです。

対応しているチャットサービス

  • Slack
  • Chatwork

サポートしている通知の種類

次のプルリクエストに関するアクションをしたときにチャットへ通知されます。

  • プルリクエストの作成
  • プルリクエストのマージ
  • プルリクエストの更新
  • プルリクエストの取り下げ
  • プルリクエストに対してのコメント

簡単な通知フロー

  1. Bitbucket 上でプルリクエストの作成やマージなどを行う
  2. Bitbucket から指定した任意のサーバに対して hook post が飛ぶ
  3. 任意サーバ上のアプリケーション(今回のツール)が post を受け取り、任意のチャットサービスに通知メッセージをポスト

必要なもの

  • PHP 5.3+ (with cURL & composer)
  • Chatwork の API トークン (Chatwork に通知する場合)
  • Slack の API トークン (Slack に通知する場合)
    • トークンは Slack API のページで発行できます。
  • Bitbucket のリポジトリ (要 Admin 権限)

インストール方法

  1. Github からソース一式ダウンロード
  2. 任意サーバにソースアップロード
  3. パーミッションの修正
    • chmod -R 777 tmp
  4. 設定ファイルの配置と設定
    • Chatwork の場合:
      • cp config/chatwork.json.default config/chatwork.json
      • vim config/chatwork.json
    • Slack の場合:
      • cp config/slack.json.default config/slack.json
      • vim config/slack.json
  5. Composer で必要プラグインインストール
    • composer install
  6. Bitbucket のリポジトリ設定から Pull Request POST の hook url 設定
    • Chatwork の場合の例:
      • http://example.com/bitbucket_event_notification/gateway.php?destination_service=chatwork&room_id=1000000000
    • Slack の場合の例:
      • http://example.com/bitbucket_event_notification/gateway.php?destination_service=slack&room_id=C1234567890

gateway.php が受け付ける GET パラメータ一覧

キー 説明 Chatwork の場合の値の例 Slack の場合の値の例
destination_service 通知先チャットサービス chatwork slack
room_id 通知先のチャットルームID (チャンネル) 1000000000 #bitbucket, C1234567890
  • room_id の指定に # が含まれる場合は URL エンコードが必要
    • 例: #bitbucket -> %23bitbucket

個人的な事情など

普段メインで使うチャットが Chatwork から Slack に変わった関係で Chatwork のほうの動作確認が手薄になってます。もし不具合などあればコメント or PR お待ちしてます。

また、プルリクエストのマージ、更新、取り下げの際に Pull Request へのリンクが無いのは仕様となっています。Approve / UnApprove の hook request に至っては、「どれかのプルリクエストに対して Approve / UnApprove された」という情報しか分からないという謎仕様になっていて、あえて通知の実装をしていません :(

Bitbucket アカウントを持ってる人は是非 issue にアクセスして vote をぽちっとお願いしますw
site / master / issues / #8340 – Pull Request POST hook does not include links to related objects (BB-9535) — Bitbucket

2015/08/19 03:19 – リポジトリの url が変更になったため更新しました。

至高のクラウドメモ環境を求めて

メモ環境に求めているもの

メモ環境に対して求めているものを整理して見なおしてみました。
同じようなことを求めている人はこの記事を読むと幸せになれるかもしれません。

  1. プレーンテキストでメモできること
    • リッチテキスト的なテキスト装飾は不要
  2. Markdown をサポートしていること
    • Markdown の入力補助
    • Markdown のプレビュー
  3. コードブロックのシンタックスハイライトに対応していること
  4. タイトルや本文で全文検索できること
  5. 保存した時点でクラウド環境に同期されること
  6. 特定のツールに依存せず、任意のツールでメモにアクセスできること
  7. メモにタグ付けできること
  8. 複数のデバイス環境でメモを閲覧・編集できること
    • Mac (メイン)
    • iPhone (サブ)
    • Windows (サブ)

今までのメモ環境

Evernote のみ

おなじみ、圧倒的に支持されているクラウドメモサービスです。

使っていて便利だなあと思いつつも、漫然とした不満を持ちながら使っていました。こうしてメモ環境に求めているものを並べてみると、多くのニーズを満たしていないことが分かりますね…。

エンジニアにとってプレーンテキスト前提の設計思想ではないこととコードブロックに対応していないことは辛いものがあるのではないでしょうか。

Evernote というぬるま湯便利環境に浸っていてはいけないとメモ環境の改革を決意しました。

新しいメモ環境

Dropbox + nvALT + MacDown + Nebulous Lite

新しいメモ環境は最終的にこのような組み合わせになりました。

メモ環境

nvALT は高速な全文テキスト検索を備えたシンプルなテキストエディタで、MacDown は賢いシンタックスハイライトを備えた Mou ライクなマークダウンエディタです。

MacDown

メモの検索やちょっとしたメモは nvALT で行い、がっつり文章を書くときやプレビューしたい時は MacDown で開くようなイメージです。

あとはメモの保存先を Dropbox にしておけば他のデバイスと同期できます。ファイルベースで保存されるので好きなツールでメモファイルにアクセスできます。

iPhone アプリは Nebulous Lite をいれてみました。全てのメモをファイル名で検索でき、一応マークダウンのプレビュー表示にも対応しています。

各ツールのいいとこ取りのような環境で、求めていた環境に近い環境ができあがりました。

nvALT の検索タグについての懸念

この環境の若干の不安要素は nvALT のタグが OpenMeta というあまり先行きが明るくないとされる規格で保存されることでしょうか。OpenMeta タグは Nebulous Lite では検索できません。

なので、ファイル名にタグ情報を含めてしまう感じで運用してみようと思っています。例えば以下のような感じで。

  • ログファイルのフィルタリング方法[bash][log][tips].md
  • ○○○○の基本設計検討MTG[design][minutes].md

…なんだかこういう基本的な仕組みを組み合わせて頑張る運用、昔 ChangeLog + Chalow + 秀丸でメモしてた頃を思い出して、少し複雑な気持ちになってしまいます。

各ツールの設定方法メモ

nvALT の設定

Preference > Notes

nvALT設定1

  • Read notes flom folder を Dropbox 上の任意フォルダに変更
  • Storage タブ
    • Plain Text Files に変更
    • 拡張子に md を追加しチェックアイコンでデフォルトに変更

Preference > Editing

nvALT設定2

  • External Text Editor を MacDown.app に変更

これで設定で開いているメモを MacDown で開けるようになります。ショートカットキーの Command + Shift + E で開くのが一番楽だと思います。

MacDown の設定

Preference > Rendering

  • Syntax highlighting in code blocks にチェック

その他、お好みで。

他に検討したメモ環境達

1. Simplenote

Simplenoteはシンプルで軽快なクラウドメモサービスで、必要最小限の機能を備えます。
かなり良さげですが Markdown のサポートが弱いため今回は見送りました。

2. Kobito

Mac のマークダウンメモアプリです。UI 構成は Evernote ライクで、Qiita にそのまま投稿もできます。

簡単かつ便利なので非常に迷いましたが、メモデータが DB に保存されるため他のツールと連携しにくいことと iOS アプリが無かったので見送りました。

3. Dropbox + Sublime Editor

Sublime に Markdown 系の拡張をいれ、Dropbox の共有フォルダをプロジェクトとして開いておくとそこそこ便利な環境が出来上がります。

今回は至高を求めていたため見送りました。

まとめ

現状で至高と思えるメモ環境ができました。ブログ名にも「メモ帳」と入ってたりするのですが、メモに関してはこれからも向き合っていくようにしたいなと思っています。

メモしていて Markdown ってやっぱり手軽に便利で素晴らしいなと思いますし、対応ツールも増えてきて嬉しい限りですが、まだまだ非エンジニアへの認知度が低い気がするのでもっと広がって欲しいなと願っています。まずは Qiita:Team に日報書く文化を社内に根付かせるところあたりから始めて見るのがいいかもしれませんw

他におすすめのツールなどあればコメントお待ちしています。