MySQL:DELETEの挙動
MySQLの大量DELETEが遅かった。すごく。
MySQLで特定の、だけど大量のデータをDELETEするとき。
こんなSQLになるとする。colはなんでもよい、それこそPKでも。
これがものすっごく遅い。これを100件くらいずつSQLを投げるほうが何故か早い。
1万件削除を1回よりも100件削除を100回投げたほうが圧倒的に早いのだ。それこそ数10倍に。
バージョンとか設定とか条件によりそうなんですが、一応こういうこともあるってことでメモ。
バグかなぁと思いつつも裏がとれなかった。あっと、バージョンは4.0系ね。
MySQLで特定の、だけど大量のデータをDELETEするとき。
- DELETE FROM table WHERE col IN (大量のデータ(数万件以上));
こんなSQLになるとする。colはなんでもよい、それこそPKでも。
これがものすっごく遅い。これを100件くらいずつSQLを投げるほうが何故か早い。
- DELETE FROM table WHERE col IN (100件くらい));
1万件削除を1回よりも100件削除を100回投げたほうが圧倒的に早いのだ。それこそ数10倍に。
バージョンとか設定とか条件によりそうなんですが、一応こういうこともあるってことでメモ。
バグかなぁと思いつつも裏がとれなかった。あっと、バージョンは4.0系ね。
SQLのチューニング
MySQLだとこのあたり。
MySQL:インデックスまとめメモ
一日目午後:MySQLの最適化 - Oliver の日記
ベンダーに依存しないところも抑えておく。
SQLを速くするぞ―お手軽パフォーマンス・チューニング
MySQLについてはもうちょっとあとでまとめます。
MySQL:インデックスまとめメモ
一日目午後:MySQLの最適化 - Oliver の日記
ベンダーに依存しないところも抑えておく。
SQLを速くするぞ―お手軽パフォーマンス・チューニング
MySQLについてはもうちょっとあとでまとめます。
こんなSQL
SQLのあんまりなさそうですが、さりげなくハマりそうなこと。
SQLで複数のカラムの値を拾うときはカンマ区切りでカラム名を並べます。
▼ 1.こんな感じ
で、ここでカンマを忘れてもエラーにはなりません。しかも結果がおかしくなります。
▼ 2.こんな感じ
理屈としてはASが省略されている構文とみなされます。
▼ 3.2とイコール
結構わかりにくいことになりそうなので気をつける。
SQLで複数のカラムの値を拾うときはカンマ区切りでカラム名を並べます。
▼ 1.こんな感じ
mysql> select a, b from table_a where id = 10;
+---+---+
| a | b |
+---+---+
| 1 | 0 |
+---+---+
で、ここでカンマを忘れてもエラーにはなりません。しかも結果がおかしくなります。
▼ 2.こんな感じ
mysql> select a b from table_a where id = 10;
+-----+
| b |
+-----+
| 1 | ← 0のはずじゃ!?
+-----+
理屈としてはASが省略されている構文とみなされます。
▼ 3.2とイコール
mysql> select a as b from table_a where id = 10;
+-----+
| b |
+-----+
| 1 |
+-----+
結構わかりにくいことになりそうなので気をつける。
MySQL 5.0 Developer Certification:インポートとエクスポート
■ Importing and Exporting Data
データのインポートとエクスポート、つまりはファイルからデータベースに取り込む、データベースからファイルに吐き出すことです。
このようにファイルへ吐き出したものは、
で取り込めます。
書き出す(読み込む)ファイルの形式はこちらで指定することができ、例えばCSV形式のときは以下のようにします。
ファイル上、NULL は NULL として書き込まれます。(エスケープが空のとき)
ENCLOSE が指定されているときは NULL は NULL として扱われますが、指定されていないときは NULL は文字列 NULL として扱われます。紛らわしい。(≧ ≦)
これらの方法はバックアップに使用することができます。
ただし、データベースを丸ごとバックアップしたり、すべてのデータベースをバックアップするときには mysqldump を使用したほうがよいのです。
mysqldump を使用したときは、普通SQL文としてダンプするのでリカバリにはmysql コマンドを使います。
また、ファイルからリカバリ(インポート)するために、LOAD DATA INFILE のコマンドラインラッパーである mysqlimport があります。
データベースのバックアップには嫌な思い出が…((((;゜Д゜)))
データのインポートとエクスポート、つまりはファイルからデータベースに取り込む、データベースからファイルに吐き出すことです。
- SELECT ... INTO OUTFILE {ファイル名}
このようにファイルへ吐き出したものは、
- LOAD DATA INFILE {ファイル名}
で取り込めます。
書き出す(読み込む)ファイルの形式はこちらで指定することができ、例えばCSV形式のときは以下のようにします。
- SELECT a,b,c INTO OUTFILE './output.csv'
- FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
- LINES TERMINATED BY 'n'
- FROM nanika_table;
ファイル上、NULL は NULL として書き込まれます。(エスケープが空のとき)
ENCLOSE が指定されているときは NULL は NULL として扱われますが、指定されていないときは NULL は文字列 NULL として扱われます。紛らわしい。(≧ ≦)
これらの方法はバックアップに使用することができます。
ただし、データベースを丸ごとバックアップしたり、すべてのデータベースをバックアップするときには mysqldump を使用したほうがよいのです。
mysqldump を使用したときは、普通SQL文としてダンプするのでリカバリにはmysql コマンドを使います。
mysql < backup.sql
また、ファイルからリカバリ(インポート)するために、LOAD DATA INFILE のコマンドラインラッパーである mysqlimport があります。
データベースのバックアップには嫌な思い出が…((((;゜Д゜)))
MySQL:特定のデータの文字コードを変換
MySQLで特定のカラムの文字コードを変換したい。
まずはエンコーディング名を調べる。
ここからcharsetカラムの値を調べておきます。例えばwinでのSJISは"cp932"となります。
必要ならwhereで条件を絞り込めばよいです。
ここで下のようなSQLを投げてみるとわかるのですが、一見変換されていないように見えます。
そんなときは16進などにしてみるとしっかり変換されていることがわかります。
よかったよかった。ちゃんと確認してないけどメモっとこう。
実際はクライアント・サーバ間での自動変換とかあるのでもうちょっと複雑です。
まずはエンコーディング名を調べる。
SHOW CHARACTER SET;
ここからcharsetカラムの値を調べておきます。例えばwinでのSJISは"cp932"となります。
- update table_name set clmn = convert(clmn using cp932);
必要ならwhereで条件を絞り込めばよいです。
ここで下のようなSQLを投げてみるとわかるのですが、一見変換されていないように見えます。
- SELECT convert("ふが" using cp932); // 結果は"ふが"
そんなときは16進などにしてみるとしっかり変換されていることがわかります。
- SELECT hex(convert("ふが" using cp932)); // 結果は"ふが"
よかったよかった。ちゃんと確認してないけどメモっとこう。
実際はクライアント・サーバ間での自動変換とかあるのでもうちょっと複雑です。



