2011年3月14日月曜日

Youtubeの動画をFedoraに取り込んでみた

日頃からYoutubeの動画をよく見ています。しかし、
・家のネット環境だと夜間はつながりにくい
・同じ動画を何度も見る
ので、Youtube動画をローカルPC(Linux)に取り込みたいと以前から思っていました。

ふと見た日経Linuxに"clive"というソフトが紹介されていたので試してみました。

記事の内容通りに設定を進めてみます。
尚、以下はFedora13でやってみた結果です。

以下をinstall…
yum install perl-Getopt-ArgvFile
yum install perl-Class-Singleton
yum install perl-HTML-TokeParser-Simple
yum install perl-Digest-SHA
yum install perl-WWW-Curl
yum install perl-Config-Tiny
yum install perl-BerkeleyDB
yum install perl-TermReadKey
yum install perl-ExtUtils-MakeMaker

以下も必要…と書いていましたが、既に入っていた為に割愛しました。
yum install perl-version
yum install perl-URI

以下を実行。
perl Makefile.PL

すると、以下のメッセージが出力されましたが、とりあえずMakeファイルは作成されました。

Checking if your kit is complete...
Looks good
Warning: prerequisite JSON::XS 2.3 not found.
Writing Makefile for clive

あとは以下二つを実行すればどこかにcliveコマンドが作成されてできあがりです。
make
make install

しかし、cliveでいざ取り込もうとすると、エラーとなりました。
clive URL

error: specify path to quvi(1) command with --quvi at /usr/local/bin/clive line 99
    main::init() called at /usr/local/bin/clive line 43
    main::main() called at /usr/local/bin/clive line 40

quviってものが原因だろうと思い、色々とやってみましたが、断念しました。
残念。。。


clive以外のソフトを探してみると、youtube-dlというものを発見しました。
で、以下を実行すればとりあえず簡単に動画のダウンロードまでは完了しました。

yum install youtube-dl
youtube-dl URL

とすればURLに指定されたYoutube動画が.flvファイルとして保存されます。

ですが、、
今度は実際に.flvファイルをtotemというソフトで実行しようとすると以下のエラーとなりました。

(totem:3138): Totem-WARNING **: Failed to create dbus proxy for org.gnome.SettingsDaemon: Could not get owner of name 'org.gnome.SettingsDaemon': no such name
** Message: Error: Your GStreamer installation is missing a plug-in.


これは、他のblogを参考にさせてもらいましたが、以下で回避可能です。
rpm -Uvh http://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-stable.noarch.rpm
rpm -Uvh http://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-stable.noarch.rpm
yum install gstreamer-ffmpeg gstreamer-plugins-bad gstreamer-plugins-ugly

上記でtotemでローカルに保存した.flvファイルをtotemで見れるようになりました。



まとめ

・Fedoraにcliveを入れようとしたが、うまくインストール出来なかった。しかし、youtube-dlはインストール出来て、Youtubeの動画ダウンロードも出来た。

・ダウンロードした.flvファイルをtotemで見ようとするとそのままの状態では見れない為、追加でinstallする必要がある。

尚、私の環境で使っているとtotemがごく稀にcoredump(異常終了)します。愛嬌ってやつですね。

2011年3月5日土曜日

H2に大量データをinsertしてみた

H2 databaseというDBで大量データinsertをやってみました。
H2のホームページを見ているとDerbyよりも高機能/高速である事を売りにしています。

H2にはDerbyと同様に組込モードとサーバモードの両方が実装されていますが、以下の確認は組込モードのみで実施おり、バージョンは1.3.152です。順序は以下のとおりです。
・H2のページからダウンロード
・CLASSPATHを設定
・ java -cp h2*.jar org.h2.tools.Shell を実行する
(もしくは、 java -cp h2*.jar org.h2.tools.Server)
・コマンドラインからテーブルの作成を実施する
create table hash ( id integer PRIMARY KEY , value varchar(40));
・insert用のCSVネタを準備する
・以下のアプリを実行する
(赤字が修正した箇所です)

import java.sql.*;
import java.io.*;
import java.util.Date.*;
public class H2ins {
        public static void main (String args[]) {
                Connection db = null;
                PreparedStatement ps = null;
                String sql = "insert into hash values(?,?)";
                String url = "jdbc:h2:testdb";
                String usr = "sa";
                String pwd = "";
                BufferedReader br = null;
                int i = 0;
                try {
                        Class.forName("org.h2.Driver");
                        db = DriverManager.getConnection(url,usr,pwd);
                        db.setAutoCommit(false);
                        ps = db.prepareStatement(sql);
                } catch (Exception ex) {
                        ex.printStackTrace();
                }
                java.util.Date d1 = new java.util.Date();
                System.out.println(d1);
                try{
                        br = new BufferedReader(new InputStreamReader(new FileInputStream("neta.csv")));
                        String line;
                        while( (line = br.readLine()) != null ){
                                i++;
                                String[] col = line.split(",");
                                int id = new Integer(col[0]);
                                String value = col[1];
                                ps.setInt(1,id);
                                ps.setString(2,value);
                                ps.executeUpdate();
                                if( i % 10000 == 0) {
                                        System.out.println(i);
                                        db.commit();
                                }
                        }
                        // データベース切断
                        db.commit();
                        ps.close();
                        db.close();
                        br.close();
                } catch (Exception ex) {
                        ex.printStackTrace();
                }
                java.util.Date d2 = new java.util.Date();
                System.out.println(d2);
        }
 }

やってみると約20sで100万件のinsertが完了します。高速だと言う謳い文句は間違っていないようです。

またH2はSqliteを意識しているようで、manual上のAndroidでの実装の箇所でSqliteでは無くH2を使う理由として以下を挙げています。(抜粋)
・参照制約+チェック制約
・豊富なデータTypeとSQL
・他DBMSの互換モード
・完全なUnicodeのサポート
・ユーザ定義関数+トリガー
・全文検索機能
・複数コネクションの許容
・データベースの暗号化

Sqliteの最新では全文検索機能等は存在しているんで、あくまでAndroidでのSqlite実装が古いバージョンで行われているという事なんでしょうか。。しかし、組込モードで複数コネクションの許容とかしてもしょうがないんじゃないかなーー。

何点か補足します。

・ Derbyでも気になりましたが、DBにConnectするタイミングで若干のタイムラグを感じます。何らかの初期処理(Classのロードとか)で時間がかかっているんでしょうかね。尚、insert時間の測定は純粋にinsertの時間のみを測っている為、Connect/Disconnectの時間は含んでいません。

・java -cp h2*.jar org.h2.tools.Shellで最初にDBの接続情報を入力しますが、Useridが自動的に"sa"となります。
(ShellからUserid/Password無にする方法が分かりませんでした)
java -cp h2*.jar org.h2.tools.Server ではuserid/passwordを無として設定できました。

2011年2月24日木曜日

Derbyに大量データをinsertしてみた

Apache Derbyに大量データをinsertしてみました。
Derbyには組み込みモードとサーバモードがありますが、組み込みモードでのみ確認しました。

Derbyを動かすまでの手順は以下の通り。基本的にはマニュアル通りです。
・Derby10.7.1.1をダウンロードする(現時点での最新)
・DERBY_HOMEを設定する
・$DERBY_HOME/binをPATHに追加
・$DERBY_HOME/lib/derby.jarをCLASSPATHに追加

・ijを実行し、testdbにConnectする
[user@user bin]$ ij
ij バージョン 10.7
ij> CONNECT 'jdbc:derby:testdb;create=true';

・hashテーブルの作成
ij> create table hash ( id integer PRIMARY KEY , value varchar(40));
0 行が挿入/更新/削除されました

下準備はこれで完了です。

毎回同様ですが、100万件のCSVネタを読み込みながらinsertを100万回行います。
以下、赤字が変更点です。
import java.sql.*;
import java.io.*;
import java.util.Date.*;

public class derbyins {
    public static void main (String args[]) {
        Connection db = null;
        PreparedStatement ps = null;
        String sql = "insert into hash values(?,?)";
        String url = "jdbc:derby:testdb";
        BufferedReader br = null;
        int i = 0;
        try {
            Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
            db = DriverManager.getConnection(url);
            db.setAutoCommit(false);
            ps = db.prepareStatement(sql);
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        java.util.Date d1 = new java.util.Date();
        System.out.println(d1);

        try{
            br = new BufferedReader(new InputStreamReader(new FileInputStream("neta.csv")));
            String line;
            while( (line = br.readLine()) != null ){
                i++;
                String[] col = line.split(",");
                int id = new Integer(col[0]);
                String value = col[1];
                ps.setInt(1,id);
                ps.setString(2,value);
                ps.executeUpdate();
                if( i % 10000 == 0) {
                    System.out.println(i);
                    db.commit();
                }
            }
            // データベース切断
            db.commit();
            ps.close();
            db.close();
            br.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        java.util.Date d2 = new java.util.Date();
        System.out.println(d2);
    }
 }

100万行insertするのに227sかかりました。SQLite3+JDBCよりもずいぶん遅く、PostgreSQL+JDBCよりも遅い結果となりました。

ApacheDerbyというものは今回初めて知ってさらっと使ってみましたが、非常に手軽に使えるのは間違いありません。Derbyのメリットをあげると以下でしょうか。
・JDBCの品質が高い(はず)
・組み込みモードとサーバモードの2種類で使える
・レプリケーションが標準で搭載されている

しかし、残念ながら日本ではDerbyを使っているという話は少なくともネット上には見受けられません。これは個人的には以下のような理由かなと思います。
・PublicDomainでは無い→Sqliteの方が使用のハードルが低い
・Sqliteの知名度に勝てない
・Javaでしか使えない
・さして高速でも無い

まあ、組み込みとサーバモード両方で使えたり、レプリケーション出来たりしても、私には使う場所が無いですね。全然Sqliteでいいです。

2011年2月17日木曜日

JavaでSqlite3に大量データをinsertしてみた

今回はJavaからsqlite3に大量データをinsertしてみました。
以前と同じですが、条件は再掲します。

まず、sqlite3でテーブルを作ります。
sqlite> CREATE TABLE hash ( id INTEGER PRIMARY KEY , value TEXT );

insertするネタはcsvファイルで
1,356a192b7913b04c54574d18c28d46e6395428ab
2,da4b9237bacccdf19c0760cab7aec4a8359010b0
3,77de68daecd823babbb58edb1c8e14d7106e83bb

1列目は数字で2列目は数字のsha1値です。
これを100万行分用意します。(neta.csv)

次にsqlite3のJDBCを探します。複数ありそうですが、今回はココにあったやつをダウンロードしました。HP上の記載を見るとsqliteは3.6.14がベースとの事です。

次に以前作成したpostgresqlへのinsertするjavaアプリを適度にsqlite用に数行修正しました。変更点は以下、赤字です。

import java.sql.*;
import java.io.*;
import java.util.Date.*;

public class sqliteins {
    public static void main (String args[]) {
        Connection db = null;
        PreparedStatement ps = null;
        String sql = "insert into hash values(?,?)";
        String url = "jdbc:sqlite:testdb";
        BufferedReader br = null;
        int i = 0;
        try {
            Class.forName("org.sqlite.JDBC");
            db = DriverManager.getConnection(url);
            db.setAutoCommit(false);
            ps = db.prepareStatement(sql);
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        java.util.Date d1 = new java.util.Date();
        System.out.println(d1);

        try{
            br = new BufferedReader(new InputStreamReader(new FileInputStream("neta.csv")));
            String line;
            while( (line = br.readLine()) != null ){
                i++;
                String[] col = line.split(",");
                int id = new Integer(col[0]);
                String value = col[1];
                    ps.setInt(1,id);
                ps.setString(2,value);
                ps.executeUpdate();
                if( i % 10000 == 0) {
                    System.out.println(i);
                    db.commit();
                }
                }
             // データベース切断
            db.commit();
            ps.close();
            db.close();
            br.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        java.util.Date d2 = new java.util.Date();
        System.out.println(d2);
    }
 }

CLASSPATHを通して実行します。
100万件のinsertの実行時間は39sでした。
因みに、
commitを10万回に1回にした場合→21s
commitを50万回に1回にした場合→19s
とさらに早くなりました。

全く同じコードでもPostgreSQLよりも断然早いです。そもそもPostgreSQLやその他DBMSとSqliteは用途が若干異なる為、比較する意味はあまり無いかもしれませんが、Sqliteはかなりいい感じ。。。ですね。

2011年2月8日火曜日

JavaでPostgreSQLに大量データをinsertしてみた

JAVAからPostgreSQLに例によって大量データをINSERTしてみました。
環境は以下です。
・Fedora13+PostgreSQL9.0 + JDBCも9.0(Type4)+JAVA6
以下のようなコードを作成しました。見苦しいところはお許しを。。

import java.sql.*;
import java.io.*;
import java.util.Date.*;
public class postgresqlins {
public static void main (String args[]) {
            Connection db = null;
            PreparedStatement ps = null; 
            String sql = "insert into hash values(?,?)";
            String url = "jdbc:postgresql:testdb";
            String usr = "postgres";
            String pwd = "postgres";
            BufferedReader br = null;
            int i = 0;
            try {
               Class.forName("org.postgresql.Driver");
               db = DriverManager.getConnection(url, usr, pwd);
               db.setAutoCommit(false);
               ps = db.prepareStatement(sql);
            ) catch (Exception ex) {
               ex.printStackTrace();
            }
            java.util.Date d1 = new java.util.Date();
            System.out.println(d1);
            try{
                 br = new BufferedReader(new(InputStreamReader(new(FileInputStream("neta.csv")));
                String line;
                while( (line = br.readLine()) != null ){
                   i++;
                   String[] col = line.split(",");
                   int id = new Integer(col[0]);
                   String value = col[1];
                   ps.setInt(1,id);
                   ps.setString(2,value);
                   ps.executeUpdate();
                   if( i % 10000 == 0) { 
                        System.out.println(i);
                        db.commit();
                   }
                }
                db.commit();
                ps.close();
                db.close();
                br.close();
           } catch (Exception ex) {
                ex.printStackTrace();
           }
           java.util.Date d2 = new java.util.Date();
           System.out.println(d2);
      }
}

以前と同様にneta.csvという100万件のデータを読み込んで、PostgreSQLにINSERTしています。INSERTにかかった時間は130sでした。
以下は感想。
・JDBCはやっぱり安定している。(Pythonと違って戸惑う事が無し!)
・Pythonのドライバと比較すると、約10倍速い。
・この差は果たして、言語的なものなのか、ドライバの優劣なのか、アプリがおかしいのか?は不明でした。
・ps = db.prepareStatement(sql) のコードをwhileループの中に書くと倍以上遅くなる。構文解析(PARSE)処理が多発するからでしょう。
・Commitタイミングを10万件にしてやってみたが、大差は無かった。

2011年1月24日月曜日

PythonでPostgresqlに大量のデータをINSERTしてみた

Python2.xでPostgresqlに大量データのInsertを試みました。
まず、SqliteやMongodbとかでやったときとの違いとしては選択出来るDriverが多いのです。

①ocpgdb1.0.3
②psycopg2-2.3.2
③PyGreSQL4.0
④pg8000-1.08
ドライバの版数は直近のものです。どれがいい・・というのは特には無さそうです。しかし、Installしてみると、④以外は全てErrorとなりました。コンパイルでエラーになるというのが共通です。何だかなー。因みに環境はFedora13+Python2.6.4+Postgresql9.0です。

サンプルみたいなものはあんまりWeb上には無いので、Manualを読みながらやってみました。

#!/usr/bin/env python
import csv
from pg8000 import DBAPI
import time

if __name__ == '__main__':
    start = time.time()
    c = DBAPI.connect(host="localhost",user="postgres",database="testdb")
    i = 0
    reader = csv.reader(open("./neta.csv"))
    for row in reader:
        id = row[0]
        value = row[1]
        cur = c.cursor()
        t = (id,value,)
        cur.execute("insert into hash2 values(%s,%s)",t)
        i += 1
        if i % 10000 == 0:
            c.commit()
            print "commit! %d" % i
    c.commit()
    c.close()
    end = time.time()
    print end-start


本当にあってるのか自信が持てないのですが、一応上記で動作しました。
例はCSVからデータを1行ずつ読み込んで100万件Insertするというものです。
しかし、integerの行に対してInsertするとエラーとなった為、テーブルを以下のようにしてid列をTEXT型で作成しました。
create table hash2 ( id TEXT PRIMARY KEY , value TEXT );

100万行のInsertには1145sかかりました。これはSqliteやMongodbと比較するとかなり遅いです。しかし冷静になって考えると1秒で約1000件弱Insertしているので、日頃の仕事で使っているDBと比較しても大差無いのかな、というところです。

以下、補足します。
・性能があがりそうなパラメータを少し変化させたが有意な差は得られませんでした。
 (wal_buffersの値を増やす、synchronous_commitをoffにする・・・等)
・id列のPRIMERY KEYを削除してやってみましたが、やはり性能差はありませんでした。
・Python3.xにはpy-postgresqlというものがあり、ドライバの品質(ドキュメント?)的には一番良さそうな気がしました。しかし、テストアプリを作るところで挫折しました。
(Transactionの実装方式がイマイチ??です)
・DBAPI2.0ではInsertするときもCursorを使うみたいです。内部的にはPreparedStatementみたいな事もしてくれてる?かは不明です。

OSSなので当然なんですが、Pythonのドライバは有志の人が勝手に作っていて、PostgreSQLのコアメンバの人は関わっていないみたいです。コアの人たちが関わってくればもうちょい扱いやすくなるのになーと思いました。

2011年1月15日土曜日

Amazon Kindle3がWifiでつながらずに苦労する

だいぶ前の話になりますが、、、

前から欲しいなーとは思っていた、Amazon Kindle。 バージョン3となり、139ドル!と魅力的な値段に。。。 これは買いだろうと思い購入。このときは3GとかWifiとか気にもしてませんでした。

米国から届いたので早速やってみたんですが、、あれっ?、そもそも本を買ったりするのってどうやるんだろう。。。ネットワークの設定のようなものが出てくるがつながらず。。全くわからん。。。

ここで(SEなのに)3GとかWiFiの意味を初めて知る。
・3G→端末だけでインターネットに接続可能。
・Wifi→端末は無線通信の機能のみ有、ネットワークにつながっているPCやルータ?等が必要。

amazonのサイトをよく見ると、
・3G+Wifiモデル→189ドル
・Wifiモデル→139ドル
となり3GがついてるモデルはWifiのみのモデルよりも高いのです。(今考えると当たり前ですが)

本当に恥ずかしながら無線LANは本で読んだ事はあるが、使った事が無い私。そもそもプロバイダーとかと新規契約する必要あるの?とかマクドとか行かないとつながらないの?とか驚くほどしょうもない事を調べる。。どうやらインターネットに繋がるPCとかがあれば、無線LAN機器を使って接続可能なようだ。

なぜか嫁さんがUSBの無線LANアダプタを持っていたので早速使ってみる。。
だめだ、つながらん。。と来る日も来る日も(夜中に)思考錯誤するが、つながらない。。
そもそもですが、Kindleは入力装置が貧弱でスムーズに入力出来ないので色々試そうとしてもものすごーーく時間がかかってしまいます。

USB型のやつはひょっとしてKindleと相性が悪いのか・・・
という訳でUSB型じゃない無線LANの親機をK'sデンキで購入。。。
これでつながらないならもうあきらめよう・・・

すると、驚くほど簡単につながった。

やった!!!



そこで前から欲しかった英語の技術書を買う。通勤時間にKindleで英語の本を読む。
何だかインテリな気分。。。(半分程度しか理解出来ないのですが。)

1か月程度たった頃、ちょっとしたはずみでKindleに少し力をかけてしまった。そのタイミングで何か鈍い感触。

もしや・・・

という訳でいとも簡単に壊れてしまいました。(電源は入るんですが、何も見えない状態)
壊れた瞬間に私のKindle熱は一瞬で冷めてしまいました。
もう当分、電子書籍には手を出さないようにします。。


                            ↓こんな感じで。。亀裂骨折です。



<まとめ>
・Kindle3は安い。基本的には常時ネット接続するような必要性は無いのでWifiのみで良いと思う。
・Kindle3は目に優しい。普通の本を見ているようなもので、PCを見るよりも目が疲れないです。
・Wifiのみの場合、無線LANの知識が無いとかなり苦戦する。まあ安いUSBのやつでもつながるとは思うんですが、身近で無線LANを使ってない場合はそこそこの無線LAN機器を買った方が無難かも。(そんな事感じたの、私だけかな・・?)
・Kindle3は電子製品なので当然壊れる。壊れた時はショックが大きい。



↓今となってはどうでもいいんですが、K'sで買った無線LAN機器です。
 これはつながりました。