2014年9月16日火曜日

MySQL 5.7で追加されたALTER TABLE .. RENAME INDEX

5.7.5が来る前に、5.7.4までのおさらい。

mysql57> SHOW CREATE TABLE t1\G
*************************** 1. row ***************************
       Table: t1
Create Table: CREATE TABLE `t1` (
  `num` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `val` varchar(32) DEFAULT NULL,
  UNIQUE KEY `num` (`num`),
  KEY `org_index` (`val`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

mysql57> ALTER TABLE t1 RENAME INDEX org_index TO renamed_index;
Query OK, 0 rows affected (0.03 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql57> SHOW CREATE TABLE t1\G
*************************** 1. row ***************************
       Table: t1
Create Table: CREATE TABLE `t1` (
  `num` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `val` varchar(32) DEFAULT NULL,
  UNIQUE KEY `num` (`num`),
  KEY `renamed_index` (`val`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)


これで、index_hogehoge_01なんて情報量ゼロのインデックスを見つけてもすぐに直せますね!


LOAD DATA INFILEで複数ファイルを食わせるのにちょっとだけ有効なTIPS

LOAD DATA INFILEで複数のファイルを順番(じゃなくてもいいけど)食わせる場合を考える。

↓こんなかんじ


$ ll *.tsv
-rw-rw-r-- 1 mysql mysql 541810051 Sep 16 10:51 20140912.tsv
-rw-rw-r-- 1 mysql mysql 523910384 Sep 16 10:52 20140913.tsv
-rw-rw-r-- 1 mysql mysql 513351897 Sep 16 10:53 20140914.tsv
-rw-rw-r-- 1 mysql mysql 513221906 Sep 16 10:54 20140915.tsv


無圧縮なファイルなら、シェルでぐるんぐるん回すのが便利。

$ for f in *.tsv ; do
> mysql -sse "LOAD DATA INFILE $f INTO TABLE .." && gzip $f
> done


成功したらgzip圧縮とかそのまんま書けるのでラク。
ただし、圧縮ファイルだと"展開" => "LOAD DATA INFILE" => "再圧縮"とか書くのはちょっと面倒だしなんかイヤだ。
あと、InfiniDBはある程度(100万行くらいだっけ?)まとめてLOAD DATA INFILEに食わせた方がデータの構築とかいっぺんに出来て速いとかそんな感じだった気がする(infinidb_use_import_for_batchinsert= 1の場合。0(MySQLのLOAD DATA INFILEをそのまま使う)場合はよく知らない)

という訳で、mkfifoを使ってます。


$ ll *.tsv.gz
-rw-rw-r-- 1 mysql mysql  2778925 Sep 12 18:04 20140722.tsv.gz
-rw-rw-r-- 1 mysql mysql  6775101 Sep 12 18:04 20140723.tsv.gz
-rw-rw-r-- 1 mysql mysql  7715720 Sep 12 18:04 20140724.tsv.gz
-rw-rw-r-- 1 mysql mysql  7811469 Sep 12 18:04 20140725.tsv.gz
-rw-rw-r-- 1 mysql mysql  8329598 Sep 12 18:05 20140726.tsv.gz
-rw-rw-r-- 1 mysql mysql  8256156 Sep 12 18:05 20140727.tsv.gz
-rw-rw-r-- 1 mysql mysql  8081465 Sep 12 18:05 20140728.tsv.gz
-rw-rw-r-- 1 mysql mysql  7881025 Sep 12 18:05 20140729.tsv.gz
-rw-rw-r-- 1 mysql mysql  7496167 Sep 12 18:06 20140730.tsv.gz
-rw-rw-r-- 1 mysql mysql  7934078 Sep 12 18:06 20140731.tsv.gz

$ mkfifo /tmp/fifo

$ zcat *.tsv.gz > /tmp/fifo


別のターミナルから

$ mysql -sse "LOAD DATA INFILE /tmp/fifo INTO TABLE .."

どうせLOAD DATA INFILEに失敗したらTRUNCATEして入れなおすからこれで十分。

InfiniDBのERROR 122 Bulkload Read Failed.

気持ちよくLOAD DATA INFILEしてたら急に現れたこんなやつ。

mysql> LOAD DATA INFILE '/data/tmp/fifo' INTO TABLE vegelog;
ERROR 122 (HY000): PM1 : Bulkload Read (thread 0) Failed for Table d1.t1.  Terminating this job.


ちなみにError 122はHandler層でのエラーらしい。

$ /usr/local/Calpont/mysql/bin/perror 122
OS error code 122:  Disk quota exceeded
MySQL error code 122: Internal (unspecified) error in handler

結論だけ書くと、テーブルのスキーマと食わせてたtsvファイルが完全に一致していなかった。
MySQLのLOAD DATA INFILEを使ってやると勝手にtruncationされて入る…んだけど、スキーマちゃんと調整しました。


mysql> SELECT @@infinidb_use_import_for_batchinsert; -- これがONだとLOAD DATA INFILEを/usr/local/Calpont/bin/cpimportにマップしてくれるので無効にする。
+---------------------------------------+
| @@infinidb_use_import_for_batchinsert |
+---------------------------------------+
|                                     1 |
+---------------------------------------+
1 row in set (0.00 sec)

mysql> SET SESSION infinidb_use_import_for_batchinsert= 0; 
Query OK, 0 rows affected (0.00 sec)

mysql> LOAD DATA INFILE '/data/tmp/fifo' INTO TABLE vegelog;
Query OK, 17208325 rows affected, 2076 warnings (5 min 35.09 sec)
Records: 17208325  Deleted: 0  Skipped: 0  Warnings: 2050

mysql> show warnings;
+---------+------+--------------------------------------------------------------------------------+
| Level   | Code | Message                                                                        |
+---------+------+--------------------------------------------------------------------------------+
| Warning | 1262 | Row 5397 was truncated; it contained more data than there were input columns   |
| Warning | 1262 | Row 5406 was truncated; it contained more data than there were input columns   |
| Warning | 1262 | Row 59575 was truncated; it contained more data than there were input columns  |
..
| Warning | 1261 | Row 329176 doesn't contain data for all columns                                |
| Warning | 1261 | Row 329176 doesn't contain data for all columns                                |
| Warning | 1261 | Row 329176 doesn't contain data for all columns                                |
+---------+------+--------------------------------------------------------------------------------+
64 rows in set (0.00 sec)

はふん。

InfiniDBにロードしている時に ERROR 122 (HY000): CAL0006: IDB-2008: The version buffer overflowed. と言われた

fifoファイル使ってごりごり流してたら怒られた。

mysql> LOAD DATA INFILE '/data/tmp/fifo' INTO TABLE infinidb_table
ERROR 122 (HY000): CAL0006: IDB-2008: The version buffer overflowed. Increase VersionBufferFileSize or limit the rows to be processed.

VersionBufferFileSizeを上げるのはいいんだけど、どれくらいが適正なのか、何をするパラメーターなのか、そもそもどこで設定するのかとかいろんな情報が出てこなくて困った。

とりあえず上げ方。


$ /usr/local/Calpont/bin/calpontConsole

InfiniDB> getSystemConfig
getsystemconfig   Tue Sep 16 11:35:41 2014

System Configuration

SystemName = calpont-1
SoftwareVersion = 4.6.0
SoftwareRelease = 1
ParentOAMModuleName = pm1
StandbyOAMModuleName = unassigned
NMSIPAddr = 0.0.0.0
ModuleHeartbeatPeriod = 10
ModuleHeartbeatCount = 3
DBRootCount = 1
DBRoot1 = /usr/local/Calpont/data1
DBRMRoot = /usr/local/Calpont/data1/systemFiles/dbrm/BRM_saves
ExternalCriticalThreshold = 90
ExternalMajorThreshold = 80
ExternalMinorThreshold = 70
MaxConcurrentTransactions = 1000
SharedMemoryTmpFile = /usr/local/Calpont/data1/systemFiles/dbrm/CalpontShm
NumVersionBufferFiles = 0
VersionBufferFileSize = 2
OIDBitmapFile = /usr/local/Calpont/data1/systemFiles/dbrm/oidbitmap
FirstOID = 3000
TransactionArchivePeriod = 10

InfiniDB> setSystemConfig VersionBufferFileSize 4
setsystemconfig   Tue Sep 16 11:36:10 2014

   Successfully set VersionBufferFileSize = 4

InfiniDB> exit   Tue Sep 16 11:36:11 2014
Exiting the Calpont Command Console

ところでこれ、再設定したあと再起動とか要るのか要らないのかもよくわからん。

ちなみに、1でダメで2に変えてもまだダメだったので4に変えたところ。



【2014/09/16 12:34】
512まで上げても改善の兆しが見られなかったので/etc/init.d/infinidb restartで再起動したら上手くいった。

# /etc/init.d/infinidb restart
Shutting down InfiniDB Database Platform
Starting InfiniDB Database Platform

# cc

Calpont InfiniDB Command Console
   enter 'help' for list of commands
   enter 'exit' to exit the Calpont InfiniDB Command Console
   use up/down arrows to recall commands


Active Alarm Counts: Critical = 0, Major = 0, Minor = 0, Warning = 0, Info = 0

Critical Active Alarms:

InfiniDB>
InfiniDB> getSystemConfig VersionBufferFileSize
getsystemconfig   Tue Sep 16 12:27:45 2014

   VersionBufferFileSize = 512

再起動しても揮発せずに残ってるのね。ってかmysqld(だけでいいのかわからんけど)の再起動が必要って言ってよ。。


【2014/09/16 19:25】
ざっと見、InnoDBでいうところのInnoDB Buffer Pool Sizeに近いんだかどうなんだかよく判らないような感じで、1~4Gくらいまで上げても良さそうなこと書いてあるけど、だったら初期値の1は何なんだ。。

http://infinidb.co/community/how-to-change-location-of-temp-directory

2014年9月11日木曜日

コンソールからMySQLでCOUNT .. GROUP BYするついでに視覚化してみる

想定しているのはこんなクエリー。


mysql56> SELECT DATE_FORMAT(timestamp, '%Y-%m') AS month, COUNT(*) AS count FROM tweets GROUP BY 1;
+---------+-------+
| month   | count |
+---------+-------+
| 2010-08 |     3 |
| 2010-09 |    90 |
| 2010-10 |    21 |
..
| 2014-07 |   608 |
| 2014-08 |   575 |
| 2014-09 |   276 |
+---------+-------+
50 rows in set (0.09 sec)


全文検索のテスト用にtweets.csvを食わせるSQL のエントリーで書いたそのまんまのDDLでtweets.csvを食わせたテーブル。
コンソールから作業していてこんなクエリーを叩いてもちょっと味気がなかったので、ひねってみた。


mysql56> SELECT DATE_FORMAT(timestamp, '%Y-%m') AS month, COUNT(*) AS count, CONCAT(REPEAT('+', COUNT(*) / 100), REPEAT('=', (COUNT(*) % 100) / 10), REPEAT('-', COUNT(*) % 10)) AS bar FROM tweets GROUP BY 1;
+---------+-------+----------------------------+
| month   | count | bar                        |
+---------+-------+----------------------------+
| 2010-08 |     3 | ---                        |
| 2010-09 |    90 | +=========                 |
| 2010-10 |    21 | ==-                        |
..
| 2014-07 |   608 | ++++++=--------            |
| 2014-08 |   575 | ++++++========-----        |
| 2014-09 |   276 | +++========------          |
+---------+-------+----------------------------+
50 rows in set (0.09 sec)

別に役に立ちはしないんだけど、人に説明するときにやって見せるとちょっと「おおお」と言われることが多い。

2014年9月8日月曜日

MyISAMなテーブルに一括でmyisamchkをかける方法

2014年も半分以上過ぎたというのにMyISAMとか言わない。

myisamchkはテーブル名または.MYIファイル名を引数に取れるので、

$ find ./ -name "*.MYI" -exec myisamchk --silent -rq {} \;

datadirにcdしてこれだけでMyISAMなテーブルを順番にmyisamchkできる。


あー、InnoDBつかいたーい。

2014年8月31日日曜日

#yapcasia 2014のおぼえがき

今年は1日目と2日目に参加しました。
内容レポートとかじゃなくて、感じたことメモ。

【1日目】
* 時間読み誤ってオープニング間に合わなかった…_| ̄|○

* すたじおさん の インフラエンジニア(狭義)は死んだ からスタート
 * 一時期元気がなさそうで心配でしたが、元気が戻ってきてそうでとても安心しました。

* けんじおじさんふしぎな感じのやつ。(タイトル全部書くのがちょっと恥ずかしいような)
 * 宇宙空間であった。。

* tokuhiromさんBDDのやつ
 * Test::Kantan 使いたい(Test::Moreですら手に余ってるけど)

* Rabisushiさんによる DBICのやつ
 * おお! という感じのツイートが多かったけど、クエリーをそんな方法でビルドするなんてそりゃあ闇も深いよとか違うことを考えていた。。

* 自分のセッションについてはこちら => 日々の覚書: WHERE狙いのキー、ORDER BY狙いのキー の話を #yapcasia でしてきました

* YappoさんJavaのやつ
 * Java書けないけど書いてみたくなった。なんてったってPerlとJavaは同じ言語だし。

* LT1日目
 * makamakaさん の完成度の高さには感動するしかない。

* 懇親会
 * kazeburoさんとちょっと話ができて、とても嬉しい。
 * あんちぽくんさん に初めて話しかけることに成功した(俺にとっては大きな一歩)ものの、多分忘れてらっしゃる(や、結構ご機嫌になったタイミングだったので)
 * Chiba.pmの面々と再会できてこれも嬉しい。


【2日目】
* kazeburoさんDockerのやつ
 * 使いどころないけど、取り敢えず遊んでみないと始まらないかなー。

* straceのやつ
 * うずらさんと同じ時間帯だって気付いてなかった…(超失礼)

* songmuさんPerlのヤーツ
 * Perlって色々できるんですね。。

* モリスさんそんなにビッグでもないやつ
 * 俺が見たセッションの中で一番感動した。
 * 全体的に松信さんぽさを感じた。
  * マシンガントーク(20分というのもあったろうけど)
  * 経験に裏打ちされた(であろう)鮮やかにポイントを押さえたトーク
  * というか、その界隈に詳しくない人間にもわかる明らかなカリスマ
 * ひとりですごい震えてた。

* LT2日目
 * いちばん刺さったのは NekogerugeさんTDD
  * 俺もほんとコレで、色んな人に色んな事を教えてもらって刺激もらって生きてる。
  * Twitter Driven Datsu-syoshinsya からの 出会い駆動コミュニティー活動 もオススメです :)


ホントすごい人が集まってすごい話がたくさんあって、(去年はそれほどそうとは思わなかったけど) YAPC最高! って感じでした。

ちなみに去年YAPCェ…ってなってたのは俺がほぼボッチだったせいだと思うので、参戦の際にはぜひ事前にYAPC行きそうな知り合いを作っておくといいと思います。そう、Chiba.pmとかね(次があるかどうかわからないけど

ポエムでした。