【メモ】MySQLの「LIMIT 0, 1」と「LIMIT 1」

mysql_logo.png 結果の先頭から1件を取得する場合、手癖で「LIMIT 0, 1」と書いてしまいがちなんですが。

SELECT * FROM items LIMIT 0, 1;
これに対してレビューで「LIMIT 1 で良くないですか?」というコメントをいただく。
SELECT * FROM items LIMIT 1;
それで何か変わるって話は聞いたことはないけど、コメント貰ったので一応仕ドキュメントを確認。

続きを読む

昨日、一時的にサービスが落ちていました。

15時くらいにサーバの1つが突然繋がらなくなり、何かやっちまったのか(例えばデータベースへの過剰なアクセスとか)と思ってサーバを再起動してみたのだけど全然ダメでおろおろしていたら、しれっとこんな告知が出てました。

メンテナンス・障害情報・機能追加|さくらインターネット公式サポートサイト

平素よりさくらインターネットをご利用いただき、誠にありがとうござ います。 本日、ご提供サービスにおきまして、以下の通り障害が発生いたしました。 ご利用中のお客様には大変ご迷惑をおかけしておりますことを深くお詫び 申し上げます。

影響範囲 : さくらのVPS 1Gプランの一部 IPアドレスが下記の範囲のお客様 219.94.245.15 ~ 219.94.245.134 障害内容 : サーバに接続できなくなる障害が発生しました。 障害によりVPSの意図しない再起動が発生しました。
ああうん、ドンピシャだよさくらさん。 いままでここまでビシッとターゲットになったことが無かったのでちょっと驚きました。発生したのが15時20分で復旧したのが18時05分。何が原因か解らないけど(機材の故障かなぁ)さすがに3時間とめられるのはきついなー。まぁ、障害発生は仕方ないか。ただせめてメールでお知らせくらいして欲しいなーと思いました。障害情報をRSSで読むといっても、それを読むRSSリーダーが今障害が起きているサーバに載っていたので。 とりあえず、データに何の問題も無くて良かったです。やれやれ。

続きを読む

MySQLのスロークエリログをmysqldumpslowで解析してファイルに書き出し、ログをローテーションする

MySQLのチューニングに当たってスロークエリログを書き出すことは良くあります。設定によっては放っておくと膨大なログになってしまうため、適度なタイミング(日毎とか週毎とか)でログローテーションしてやります。logrotateを使うのが常套手段。 スロークエリログの解析にはmysqldumpslowを使用します。mysqldumpslowを使用するとログを解析した上で、オプションに従って並べ替えて出力してくれます。ログ全体のまとめになるので、定期的これを実行すれば、どれくらいの頻度でスロークエリが発生しているかを定量的に計ることが出来ます。 …というわけで、この2つを組み合わせてみました。

/etc/logrotate.d/mysql

/var/log/mysql-slow.log {
# create 600 mysql mysql
notifempty
daily
rotate 5
missingok
prerotate
EXT=`/bin/date +%Y%m%d`
/usr/bin/mysqldumpslow -s t /var/log/mysql-slow.log > /var/log/mysql/mysql-slow.${EXT}.log
endscript
postrotate
# just if mysqld is really running
if test -x /usr/bin/mysqladmin && \
/usr/bin/mysqladmin ping &>/dev/null
then
/usr/bin/mysqladmin flush-logs
fi
endscript
}

続きを読む

MySQLのINSERT文(方法ごとの処理時間比較)

大量のデータをINSERTする場面があってなんとか高速化できないかと思って、 以下の手法を比較してみた。

  1. 1件ずつINSERTする
  2. トランザクションを使用する
  3. 1クエリでまとめてINSERTする
テスト環境は以下の通り。
  • MySQL 5.1
  • テーブルはInnoDB、AUTO_INCREMENT付き(innodb_autoinc_lock_mode=1)
  • PHP 5.3.6
1000件、3000件、5000件、10000件と件数を増やしながらそれぞれ5回ずつ試行して平均を取っている。 使用したコードは最後に。

続きを読む

InnoDBでのINSERT IGNOREとAUTO_INCREMENT

InnoDBでINSERT IGNOREを繰り返してたら、レコード数は増えてないのに、 AUTO_INCREMENTだけがガンガン増えててびっくり。おかげでidの値が飛んでる。 なんなんだろうと思ったらこれ、MySQL 5.1.22以降の仕様なんですね。 以下、マニュアルから引用。強調はおいら。

簡単に言えば、このロックモードの重要な効果は、スケーラビリティーの大幅な向上です。このモードは、ステートメントベースのレプリケーションで使用しても安全です。さらに、「従来」 ロックモードの場合と同じく、任意のステートメントによって割り当てられた自動インクリメント番号が「連続」した値になります。このモードでは 「従来」 モードと比較して、ある重要な例外を除けば、自動インクリメントを使用する任意のステートメントでの意味上の「違い」はありません。 その例外とは、ユーザーが複数行 「単純挿入」 の全部ではなく一部の行で AUTO_INCREMENT カラムの明示的な値を提供する 「混在モード挿入」 の場合です。そのような挿入では、InnoDB は挿入行数よりも多くの自動インクリメント値を割り当てます。ただし、自動的に割り当てられる値はすべて連続的に生成されるため、直前に実行されたステートメントによって生成された自動インクリメント値よりも値が大きくなります。「余分」 な番号は失われます。 INSERT … ON DUPLICATE KEY UPDATE を使用する場合にも似たような状況になります。このステートメントも 「混在モード挿入」 として分類されていますが、これは、自動インクリメント値が必ずしもすべての行で生成されないからです。
 
なるほど。

続きを読む

【メモ】datetime型のデータから日付ごとの最小/最大/平均を取得する

datetime型で次々にデータをつっこんでいって、 集計時には日付ごとのデータを出したいってことがよくあるのですけれど、 date関数を使えば超早いらしいです(MySQL 4.1.1以降)。 [MySQL]datetime型のデータから日付別の集計を行う | 1人で稼ぐ日記 MySQL :: MySQL 4.1 リファレンスマニュアル :: 6.3.4 日付と時刻関数 なるほど。

続きを読む