2008-03-05 22:07:23

CatalystアプリケーションのUnicode化2

[ Catalyst ] [ DBIx::Class ] [ MySQL ]

・FillInForm安全対策

cpan[1]> install Catalyst::Plugin::FillInForm::ForceUTF8
ex) http://blog.hide-k.net/archives/2007/03/catalyst_2.php
※Catalyst::Plugin::FillInForm だと Catalyst::Plugin::Unicode の前にロードする必要があり、多分いつかハマるのでNG

・DBIx::Class で mysql 使う時

方法1 - DBD::mysql のオプションを使う
(http://search.cpan.org/~capttofu/DBD-mysql-4.006/lib/DBD/mysql.pm)
$ vim lib/MyApp/Model/MyAppDB.pm

package MyApp::Model::MyAppDB;
use strict;
use base 'Catalyst::Model::DBIC::Schema';
__PACKAGE__->config(
    schema_class => 'MyApp::Schema',
    connect_info => [
        'dbi:mysql:myappdb',
        'user',
        'password',
        {
            mysql_enable_utf8 => 1
        }
    ],
);
1;

方法2 - DBIx::Class::UTF8Columns を使う
(http://search.cpan.org/~jrobinson/DBIx-Class-0.08009/lib/DBIx/Class/UTF8Columns.pm)
$ vim lib/MyApp/Schema/Hoge.pm

package MyApp::Schema::Hoge;
use strict;
use warnings;
use base 'DBIx::Class';
__PACKAGE__->load_components(qw/UTF8Columns Core/);
__PACKAGE__->table("tag");
__PACKAGE__->add_columns(
  "shop",
  { data_type => "INT", default_value => "", is_nullable => 0, size => 11 },
  "id",
  { data_type => "SMALLINT", default_value => "", is_nullable => 0, size => 5 },
  "name",
  { data_type => "VARCHAR", default_value => "", is_nullable => 0, size => 255 },
);
__PACKAGE__->set_primary_key("shop", "id");
__PACKAGE__->utf8_columns(qw/name/);    #static で作った場合、add_columns の後に記述すること
1;

どちらでもフラグ付きで放り込んで、フラグ付きで取り出せる。
もちろんmysqlでも普通に見える。
備考:方法1のほうが便利・・・しかし
This option is experimental and may change in future versions.
ex) http://search.cpan.org/~capttofu/DBD-mysql-4.006/lib/DBD/mysql.pm

さらに参考
http://search.cpan.org/~cfranks/HTML-FormFu-0.02004/lib/HTML/FormFu/Manual/Unicode.pod

2008-03-05 22:00:31

DBICでMySQLのtimestamp

[ Catalyst ] [ DBIx::Class ] [ MySQL ]

TIMESTAMP型のカラムは CatalystのHelperでスキーマを作ると

  "time",
  {
    data_type => "TIMESTAMP",
    default_value => "CURRENT_TIMESTAMP",
    is_nullable => 0,
    size => 14,
  },

こんなのができる。
insert や他のカラムをupdateすると現在時刻が入る。

意識的に入れるときは undef を入れる。
$c->model('MyAppDB::Hoge')->update_or_create({
    time => undef,
});

Fedora-7,MySQL-5.0.41,DBIC-0.08009,Perl-5.10.0

2007-09-06 00:54:24

mysqlの便利だけど忘れるコマンド

[ MySQL ]

チェック
check table country,format,stock;

チェック2
check table goods extended;

リペア
repair table country,format,stock;

最適化
optimize table country,format,stock;

インデックスのみ最適化
analyze table country,format,stock;

置換
update goods set review=REPLACE(review,'&lt;','<');
update goods set format=REPLACE(format,'&quot;','"');
update goods set title=REPLACE(title,'&amp;','&');

ファイル書き出し(エクスポート)
select * into outfile '/home/user/country.sql' from country;

インデックス確認
show index from goods;

インデックス作成
create index open_date_index on goods (open_date);
create index open_close_index on goods (open_date,close_date);

インデックス削除
drop index open_date_index on goods;

スレーブ確認
show slave status \G;

インデックス動作確認
explain SELECT me.goods_id, me.title FROM goods me ORDER BY format \G;

テキストデータインポート(IGNORE で重複ユニークキースキップ)
LOAD DATA INFILE "/tmp/hoge.tab" IGNORE INTO TABLE hoge;

テーブル内容高速削除
TRUNCATE TABLE goods;

遅いログの記録設定
vim /etc/my.cnf
set-variable=log-slow-queries=/var/log/slowsql.log
set-variable=long_query_time=1 ←1秒以上かかったコマンドの記録
set-variable=log-queries-not-using-indexes ←インデックスを使用しないコマンドの記録

スレーブ開始
ex)http://www.irori.org/doc/mysql-rep.html
mysql> CHANGE MASTER TO
    -> MASTER_HOST = 'mymaster',
    -> MASTER_USER = 'repl',
    -> MASTER_PASSWORD = 'qa55wd',
    -> MASTER_LOG_FILE = 'mymaster-bin.001',
    -> MASTER_LOG_POS = 359;
mysql> START SLAVE;

スレイブストップ
STOP SLAVE;

カラムを最後に追加する
ALTER TABLE テーブル名 ADD 追加するカラム名 型;

JOIN 使いつつ ORDER BY で別テーブルの複数キーを指定すると非常に遅い。
非正規化するのが吉。

文字列連結
SELECT CONCAT(name_en, ' ', name_jp) FROM goods WHERE id='X55';
ex)http://dev.mysql.com/doc/refman/5.1/ja/string-functions.html

サブクエリでアップデート+文字列連結
UPDATE goods_data SET search_name = (SELECT CONCAT(name_en, ' ', name_jp) FROM goods WHERE id=goods_data.goods);

使えるテーブルタイプ一覧表示
SHOW TABLE TYPES;

テーブルステータス表示
SHOW TABLE STATUS;

2007-07-25 23:57:20

MeCab-Senna-TritonnのRPMインストールとCatalystでのSearch

[ Catalyst ] [ DBIx::Class ] [ MySQL ]

※Fedora7を使用

[mecab導入]
楽だ。
yum -y mecab mecab-devel mecab-ipadic perl-mecab


[senna導入]
cd /home/hoge/rpmbuild/SOURCES
wget http://iij.dl.sourceforge.jp/senna/25607/senna-1.0.7.tar.gz
tar xzvf senna-1.0.7.tar.gz
SPEC発見。
cp senna-1.0.7/senna.spec /home/hoge/rpmbuild/SPECS/.
cd ../
rpmbuild -bb SPECS/senna.spec

あら、エラーが出た。
error: File /usr/src/redhat/SOURCES/libsenna-1.0.7.tar.gz: No such file or directory

SPEC修正。
vi SPECS/senna.spec

@@ -2,7 +2,7 @@
 %define release 1

 Summary: An Embeddable Fulltext Search Engine
-Name: libsenna
+Name: senna
 Version: %{version}
 Release: %{release}
 License: LGPL

再度ビルド。
rpmbuild -bb SPECS/senna.spec

以下のメッセージが出てRPMができた。
Wrote: /home/hoge/rpmbuild/RPMS/i386/senna-1.0.7-1.i386.rpm
Wrote: /home/hoge/rpmbuild/RPMS/i386/senna-devel-1.0.7-1.i386.rpm
Wrote: /home/hoge/rpmbuild/RPMS/i386/senna-debuginfo-1.0.7-1.i386.rpm

インストール
cd RPMS/i386/
rpm -ivh senna-1.0.7-1.i386.rpm senna-debuginfo-1.0.7-1.i386.rpm senna-devel-1.0.7-1.i386.rpm


[Tritonn + MySQL導入]
SennaのMySQLバインディングパッチが Tritonn という名の別プロジェクトになったらしい。
ex) http://qwik.jp/tritonn/about.html

cd SOURCES/
wget http://iij.dl.sourceforge.jp/tritonn/26391/mysql-5.0.41-tritonn-1.0.3.tar.gz
tar xzvf mysql-5.0.41-tritonn-1.0.3.tar.gz
現在使用中のディストリ版MySQLを上書きして使いたいので、RPM化する際に mysql-5.0.41 になってもらうことにする。
mv mysql-5.0.41-tritonn-1.0.3 mysql-5.0.41

Fedoraのtestにmysql-5.0.45-1があがっていたのでSRPMをもらう。
cd ../SRPMS/
wget ftp://ftp.riken.jp/Linux/fedora/updates/testing/7/SRPMS/mysql-5.0.45-1.fc7.src.rpm
rpm -ivh mysql-5.0.45-1.fc7.src.rpm
SPECを流用。
cd ../SPECS/
cp mysql.spec mysql-tritonn.spec
vi mysql-tritonn.spec

以下のように変更。
make testは通らないのでコメントアウトした(普通に./configureしても make test はエラーになったのであきらめた)。
--- mysql.spec  2007-07-23 07:16:27.000000000 +0900
+++ mysql-tritonn.spec  2007-07-25 10:31:57.000000000 +0900
@@ -1,15 +1,15 @@
 Name: mysql
-Version: 5.0.45
+Version: 5.0.41
 Release: 1%{?dist}
-Summary: MySQL client programs and shared libraries
+Summary: MySQL client programs and shared libraries and tritonn
 License: GPL
 Group: Applications/Databases
 URL: http://www.mysql.com

 # Regression tests take a long time, you can skip 'em with this
 %{!?runselftest:%define runselftest 1}

-Source0: http://dev.mysql.com/get/Downloads/MySQL-5.0/mysql-%{version}.tar.gz
+Source0: mysql-5.0.41.tar.gz
 Source1: mysql.init
 Source3: my.cnf
 Source4: scriptstub.c
@@ -153,6 +153,8 @@
 export CFLAGS CXXFLAGS

 %configure \
+       --with-senna=/usr \
+       --with-mecab=/usr \
        --with-readline \
        --with-openssl \
        --without-debug \
@@ -189,7 +191,7 @@
   esac
   export MTR_BUILD_THREAD

-  make test
+#  make test
 %endif

 %install


必要なファイルをコピーする(このままではman 関連が無くてエラーになる - 2007.7.26 0:16追記 mysql-5.0.41-tritonn-1.0.3.tar.gz のソース修正されてman入ったかも~未確認)。
cd ../SOURCES/
tar xzvf mysql-5.0.45.tar.gz
cp mysql-5.0.45/man/* mysql-5.0.41/man/.

mysql-5.041(Tritonn内蔵版)のtarボール作成する。
tar czvf mysql-5.0.41.tar.gz mysql-5.0.41

Build時必要なものをインストール。
yum install gperf readline-devel ncurses-devel

ビルド開始。
cd ../SPECS/
rpmbuild -ba mysql-tritonn.spec

できた。
Wrote: /home/hoge/rpmbuild/SRPMS/mysql-5.0.41-1.fc7.src.rpm
Wrote: /home/hoge/rpmbuild/RPMS/i386/mysql-5.0.41-1.fc7.i386.rpm
Wrote: /home/hoge/rpmbuild/RPMS/i386/mysql-libs-5.0.41-1.fc7.i386.rpm
Wrote: /home/hoge/rpmbuild/RPMS/i386/mysql-server-5.0.41-1.fc7.i386.rpm
Wrote: /home/hoge/rpmbuild/RPMS/i386/mysql-devel-5.0.41-1.fc7.i386.rpm
Wrote: /home/hoge/rpmbuild/RPMS/i386/mysql-bench-5.0.41-1.fc7.i386.rpm
Wrote: /home/hoge/rpmbuild/RPMS/i386/mysql-test-5.0.41-1.fc7.i386.rpm
Wrote: /home/hoge/rpmbuild/RPMS/i386/mysql-debuginfo-5.0.41-1.fc7.i386.rpm

ここに置いておきます。
mysql-5.0.41-1.fc7.src.rpm
mysql-5.0.41-1.fc7.i386.rpm
mysql-bench-5.0.41-1.fc7.i386.rpm
mysql-debuginfo-5.0.41-1.fc7.i386.rpm
mysql-devel-5.0.41-1.fc7.i386.rpm
mysql-libs-5.0.41-1.fc7.i386.rpm
mysql-server-5.0.41-1.fc7.i386.rpm
mysql-test-5.0.41-1.fc7.i386.rpm

インストールする。
cd /home/hoge/rpmbuild/RPMS/i386/
rpm -Uvh mysql-*

以下URL参照に動作確認した。
http://qwik.jp/senna/check_install.html

念のためyumで上書きされないように yum.conf を編集。
vi /etc/yum.conf
exclude=mysql*


[Catalystで使ってみる]
FULLTEXTインデックスを作る。
mysql> CREATE FULLTEXT INDEX review_index ON goods_att(review);

カラムが text 型の場合、最大値255以下で指定
mysql> drop index review_index on goods_att;
mysql> CREATE FULLTEXT INDEX review_index ON goods_att(review(255));

以下の2パターンが使えるようだ。
ex1) http://asakura.g.hatena.ne.jp/asakura-t/comment?date=20070405
use SQL::Abstract::Fulltext::MySQL;
my $rs = $c->model('GoodsDB::GoodsAtt')->search({
    -fulltext => {
        -match   => 'review',
        -against => $q,
        -boolean => 1,
    },
});

ex2) http://blog.hide-k.net/archives/2006/08/dbixclassfullte.php
my $rs = $c->model('GoodsDB::GoodsAtt')->search({
})->search_literal('match(review) against(?)', $q);

ex1を使うことにする。
SQL::Abstract::Fulltext::MySQLを use して使用することにする。

Bench Mark してみる(マシンスペック - Celeron2.5GHz, Memory 384MB)。
Records: 121141

まずは普通に mysql クライアントから。
mysql> select count(*) from goods_att where match(review) against('強力');
+----------+
| count(*) |
+----------+
|     1492 |
+----------+
1 row in set (0.01 sec)

like 検索と比べる。
mysql> select count(*) from goods_att where review LIKE "%強力%";;
+----------+
| count(*) |
+----------+
|     1492 |
+----------+
1 row in set (0.62 sec)

次にCatalystで比較。4ワードで試した。
senna
0.339656s
0.840683s
6.052170s
0.880074s

like
2.199280s
1.740971s
12.650366s
1.220464s

2007-07-25 22:28:14

latin1で保存されていたEUC-JPをダンプ

[ MySQL ]

mysqldump -uroot --default-character-set=latin1 DBNAME > DBNAME.sql

- nkfでeuc-jpからutf8変換

nkf -E -w DBNAME.sql > DBNAME_utf8.sql

- viで置換

:%s/NAMES latin1/NAMES binary/g
:%s/CHARSET=latin1;/CHARSET=binary;/g
他は必要な部分を。

- 再度euc-jpへ

nkf -e DBNAME_utf8.sql > DBNAME_euc.sql

- リストア

create database DBNAME CHARACTER SET binary;
mysql -uroot DBNAME < DBNAME_euc.sql

※binaryにしたりeuc-jpに再変換したりしたのはアプリケーション&MySQL設定の都合

2007-06-11 16:24:52

レコード内文字列置換

[ MySQL ]

tableテーブルの columnカラム内の aaaa を bbbb に置換。

UPDATE `table` SET column=REPLACE(column,'aaaa','bbbb');

2007-01-30 19:33:27

ALTER

[ MySQL ]

MySQL5.0のtext型は最大値65535バイト(PostgreSQLは無制限)。
オーバーフローするようなら変更する。

ALTER TABLE table MODIFY column mediumtext;

ex:) http://dev.mysql.com/doc/refman/4.1/ja/string-types.html

2007-01-30 19:15:59

SELECT結果のテキスト書き出し

[ MySQL ]

$mysql DBNAME > output.txt
SELECT column FROM table WHERE name='hoge';
quit

2007-01-04 10:27:19

viewによる高速化はできない

[ MySQL ]

MySQL5.0のviewによる高速化はできない。
単なるエイリアスとしての機能のようだ。

[view作成]
CREATE VIEW view_table AS
SELECT
 table_a.aaa,table_b.bbb,table_c.ccc
FROM
 table_a
LEFT JOIN
 table_b ON ( table_a.id = table_b.id ) 
JOIN
 table_c ON ( table_a.id = table_c.id )
;

普通にJOINしてSELECTしても、VIEWに対してSELECTしても、所要時間は同じ。