コレクションを識別するための名前です(文字列です)。Identifierと内部的に1:1に対応しています。命名規則は先頭が英字で他は英数かアンダーバー、ハイフンで構成されます。ハイフンを除けば常識的なプログラミング言語の変数名の規則と同じです。Documentを識別するための内部ID(整数型です)。これを直接使うことはほとんどありません。↓のDocumentHandleを通常は使います。Documentを識別するためのHandle名(文字列です)。DocumentIDとなります。Version)のバージョン番号にあたるものです。Etagを併せて説明しないといけないのですが、今回は省略します・・。HTTP-RESTのInterfaceではCollectionNameもCollectionIDも両方サポートしています。Documentの実際の値はJSONになります。JSONObjectでも、JsonArrayでも大丈夫ですし、AvocadoDBはKVSでもあるのでJSONの要素(文字列、整数、Boolean、NULL)も受け付けます。GraphDBとしてのAvocadoDBも説明します。Graph構造はVertexとEdgeで構成されます。VertexはDocumentに相当します。Edgeは専用で作るAPIが存在します。有向グラフか無向グラフ(要はエッジの向きがあるか無いか)はEdgeを作るときには指定できません。基本は有効グラフとしてEdgeを作ります。outを指定して取ります。VertexはDocumentなので任意の属性を保存する事ができ、Edgeも同様に任意の属性を保存する事ができます。Indexの種類は今は3つあります。(B-treeが無い理由はVideo見ればわかったりするのかな?)。Indexは要素は2つまでの制約があります。Indexはユニーク制約を付けることができます。HashとSkipListsの特性の違いの説明は必要ありませんよね。CollectionやDocumentを作るときに、Diskへの書き込みを同期化するかのオプションがあります。InnoDBのFlushパラメータみたいなのですが、これは基本的にAsyncにしないと性能が出ません。(※性能テストはRoadMapの1.0betaで行う事になっているので、今の段階で性能云々を言うのはちょっとお門違いです)さて、次はJavaで扱う方法です。Javaのドライバはこちらにあります。JARファイル作っていません。作った方がいいかな?※prototypeですので、サーバが落ちている時のハンドリングを入れていません。Edgeの操作ができます。使い方はREADMEかExampleに書いてあります。単体テストを見るのが良いと思います。以下はDocumentを1000個適当に作ってクエリで検索するサンプルです。Cursorを扱いやすくするためにResultSetを作ってみました。}}グラフも扱えます。グラフの扱い方は以下のようになります。効果的にトラバーサルする方法がまだ提供されていません。TinkerPopのBluePrintsとGremlinに対応するらしいので、そのあたりで出来ることは将来的にできるようになると思います。(私はGremlinでGraphを操作した事がないので詳細はわかりません。e3=v2->v3)作り、v0のエッジを求めています。Hiveこんにちは、ポテトサラダを極めようと心に決めたタムタムです。(昨日作って食べたら満足しました(・w・))今日はHiveのパッチの書き方をまとめます。Hadoop本体とはちょっと作法が違います。Hadoop本体はパッチを投げると自動でJenkinsがテストしてくれたりするらしいのですが、Hiveはそんなことやってくれません。パッチもJIRAに添付するだけではダメで、Phabricator(Reviewボードみたいなもの)というツールを使ってDiffをアップしてReviewしてもらう必要があります。今回は実際にHIVE-2703のパッチを投げるまでの手順を書いていきます。こちらの内容と被っていますが、こっちでは説明しきれなかったところも書いていきます。手順はsubversionの手順になっています。ぶっちゃけgitの方をオススメします。subversionだと複数のパッチを書くときにローカルでブランチを切れないのでとってもとってもつらいです・・。HIVE-xxxでパッチをあげることができなかったからです)なお私はFedora16をVirtualBoxの上で動かして開発しています。(MacbookとかオシャレなPC持っていません・・)あと、Hadoopの環境は普通に作っておいてください。ローカルモードで良いです。今やいろんな本が出ていますが、Hadoop徹底入門がオススメです。した手順は以下のようになります。ソースを落とすソースをいじるテストする(JIRAで適宜コメント書いたり、やりとりしたり)Phabricatorでreviewして貰う最終版のDIFFをJIRAに添付する(ASFライセンス付ける)細かい手順を説明していきます。ソースを落としてEclipseのプロジェクトを作ります。(Eclipse使わなくてもパッチは投稿できます。JavaのソースをIDE無しで書くのは結構つらいと思います。HIVE-2904のパッチを当てましょう。今のバージョンだと正しいEclipseのテンプレートを作ってくれません。パッチのバージョンを変更しました。最新のソースだとDDLTaskがjson形式で出力できるようになっていて、JsonMetaDataFormatterがjacksonに依存するようになっていました。これでhive-trunkにeclipseのprojectファイルが出来ています。あとはEclipseからインポートするだけです。Eclipseの使い方は今更説明するようなものではないので省略します。注意点としては、ワークスペースの文字コードをUTF-8に、JDKは6を使いましょう。保管アクション」の設定でインポートの編成が行われるようになっています。パッチを書いた時にdiffを取ったらいじっていないところも変更されている事があります。これは気にしたら負けです。1つ、プロジェクトの設定の「ビルダー」で「Hive_Ant_Builder」のチェックは外した方が良いです。保存する度にAntが走って重めのビルドが走ることになってちょっとイラッとします。ここまでで、開発環境は整いました。いうわけで、普通に開発をしましょう。パッチを出す時は基本的にテストケースも一緒に追加します。(パッチの内容にもよりますけど)。次にテストの方法です。単体テストはJUnitで書かれています。Eclipse用のプロジェクトを生成した時に、実行構成も既に設定されています。ディレクトリなど)が入っています。どのクラスがどの単体テストが担当しているのかは、クラスの参照を調べればなんとなく推測できます。関連する単体テストがピンポイントで通るようにするのが良いです、なお、UDF関数やクエリのテストはまたちょっと違います。後者のテストの方法は以下のようにします。このテストは、「ql/src/test/queries/clientpositive/timestamp_udf.q」を実行した時に「ql/src/test/results/clientpositive/timestamp_udf.q.out」の結果になるかというテストです。前回の記事にも書いてあります。-Dqfileを省略すると全部のテストを実行します。testこのあたりをピンポイントで実行してから、最後に全体のテストを実行します。非情に時間がかかります。4,5時間は覚悟してください。寝る前に実行しましょう。いうファイルが生成されます。このファイルにテストの結果が書いてあります。diffを取って差分を確認してください。(※最初に環境構築をするためにパッチを当てたやつは除外する必要があります。HIVE-xxxx.1.patch.txtgitの場合は、以下のような感じです。HIVE-xxxx.1.patch.txtこれでパッチを投げる準備ができました。(後述するPhabricatorを使わない場合は、このDIFFをJIRAにファイル添付すれば良いです。)チケットの開き方は前回の記事を参考にしてください。※こんな事を書くと怒られるかもしれませんが、ぶっちゃけ英語なんて適当で通じます(たぶん)。英語が出来なくてウジウジするくらいならコードを書いてパッチを投げましょう。(もしくは知り合いに英訳して貰いましょう)。自分たちが外国人のニンジャ語を理解できるように向こうの人もきっと理解してくれます。パッチの投稿の仕方です。Phabricatorをインストールする必要があります。以下のURLを参考にします。arcanist/resources/shell/bash-completionその後、以下のコマンドを叩いて準備をします。環境変数PATHに通しておくと良いです。install-certificatePhabricatorにパッチを投げる手順は以下になります。これは実際にsvnかgitでdiffを取ってPhabricatorに投稿します。これでJIRAにパッチが添付されます。Patch」を押します。Availableになります。パッチがNGな場合は、レビューの内容やコメントの内容を見て修正しましょう。レビューが終わったら最終バージョンのパッチをJIRAに添付します。添付する時はASFライセンスを付与しましょう。この時に新機能の追加や互換性が無くなる変更の場合はReleaseNoteを各必要があります。私はHiveにはそんなに詳しくない初級者ですが、何か困ったことがあれば協力できるかも。Hackathonというものがあります。http://www.zusaar.com/event/250002私が参加した時は、JIRAの使い方とパッチの書き方を最初に教えていただきました。基本は黙々とハッカソンするわけですが、お菓子を食べながらプロジェクターにソースを映してアレやコレやと楽しかったです。開発環境とJavaさえ書ければ、英語は出来なくてもみんな英語が出来るので誰かが助けてくれます。Hadoopのここが気にくわないわー。Hiveのここが気にくわないわー。あのBug放置されてるわー、直したいわー。いう人は参加を考えてみると良いかも。AvocadoDBこんにちは、某所で豆腐ハンバーグを食べないといけないくらい貧乏ということになっているタムタムです。いうものを紹介したいと思います。間違いや勘違いがあったらご指摘くださいませ。足したようなものです。Webサイトに掲載されている特徴を列挙すると以下のようになります。スキーマレスですクライアント・サーバモデル(アプリケーションサーバとして動作)です。RESTインターフェースを提供しています。KTのLuaバインディングっぽい事がもっと簡単にできます)マルチスレッドで動作しますMVCCモデルです。ドキュメントは(内部的には追加オンリー)でバージョン管理していて、古いバージョンは自動でガベコレされます。(PostgreSQLみたいなやつ)柔軟なデータ構造を提供します。単純なKVS、DocumentDB、グラフDB(これはまだRESTで扱えないけど、シェルからはJSを介して使えます)インデックスを選択できます。スキップリストやn-gramインデックスとか。(将来的にはHashIndexやGeoIndexも?)永続性の設定ができます。モダンなストレージに対応しています。さんからコメントがあったので記載しておきます。何が熱いかと言うと、開発者のレスポンスの早さと開発速度がちょっとクレイジーなくらいはやいところ。今だとAvocadoDBについてTweetすれば関係者がレスポンスくれます。日本語でもだいたい反応してくれます。(というか、TwitterをAvocadoDBで検索すると、開発者か日本人しかつぶやいていません・・)あと、絶賛開発中なのにドキュメントが綺麗・豊富に揃っています。見ればだいたいの事は載っています。(目次からたどれないページがいくつかあるように感じるので、ページ一覧から行く方が早いです)常識的なC++で書かれているので(一部Cのコードもあります)ソースコードは読みやすいです。コメントもきちんと書いてあります。RESTに関してはコアな機能がC++で実装されていて、ほとんどがJSで実装されておりコアな機能を呼び出しているという形式になっています。開発者がどれくらい熱いかと言うと、アレな会社で一般人なイケメンをやっている人のTweetに対してVideoで返信してくるとか。http://www.avocadodb.org/2012/04/03/skip-list-indices-in-avocadodb各言語のDriverというかClientというかバインディングみたいなものは、公式ではPHPのものがあります。他の言語については、皆様が絶賛開発中です(なぜかみんな日本人)。現在の対応状況がロードマップに記載されています。JavaのDriverは私が絶賛開発中でございます。進捗としては、DocumentDBとして使えるところまでは出来ています。今ユニットテストをいっぱい書いてます・・。testが出来なくて死ぬので。AvocadoJDBCDriverという構成になります。AvocadoClientはオブジェクト指向的に扱うためのインターフェースでDocumentクラスがcreateとかを持つようになります。AvocadoDriverはREST-APIとほぼ1:1に対応した低レイヤーのインターフェースになります。AvocadoJDBCDriverはJDBCドライバとして実装しているものになります。今作っているのはAvocadoDriverです。Client/Driverと分けたのは、CommonsHttpClient4やsvnkitのような感じの低レイヤーのものと高レイヤーのものとで分離したかったからです。こんな感じで使いますというのをGistに簡単なサンプルを載せました。(検証コードがあちこちにあって見づらいですが、使い方は至ってシンプルだと思います。)まだgithubにはpushしてません。AvocadoDBのインストールの方法や簡単な使い方、グロッサリーの説明は別の記事に書きます。JavaリハビリのためにMurmurHashをJavaに移植してみました。Version1,2,3全てありますので、32bit,64bit,128bitのハッシュを求めることができます。https://github.com/tamtam180/MurmurHash-For-Javaオリジナルと同じ結果を返すことは確認済みです。MurmurHashってなんぞという人はオリジナルのサイトをどうぞ。Projectの方が良いような気がしてる。パッケージをダウンロードさせたい場合、Githubではどうやるのかわかんないや。実行すると、以下のエラーが発生します。place.<if>というタスクが無いよーというエラーです。このJARファイルのIfTaskは中に入っており、build.xml中でtaskdefしてあげないといけません。以下の定義を追加してあげる必要があります。${hive.root}/build.xmlには定義されているんですけどね。</classpath></taskdef>この定義をql/build.xmlのgen-testのtarget配下に書いてもいいのですが、いろんなbuild.xmlがbuild-common.xmlをimportしていて、さらにbuild-common.xmlでも<if>タスクを使っているので、build-common.xmlに定義するのが良いかと思います。diffはこんな感じです。value="[conf]/[artifact]-[revision](-[classifier]).[ext]"/>つか、誰も困って無いのかな・・。それっぽいチケットも無いんだけど。Spring発熱でDOWNしているタムタムです。インフルエンザのようなすごい高熱というわけでもなく、プリン食べて家でしょぼーんとしてます。今回はHiveのUDF一覧を自動生成してみました。Hive0.8用はURLを変更して、こちらにtrunk(rev1293519)のバージョンを起きました。reflect関数とかWikiには載っていないと思います。builtinと書いてあるやつはFunctionRegistryのstaticイニシャライザで関数登録しているやつです。Alias名がある関数はそれぞれ1つの項目に作ってあります。作り方は至ってシンプルで、UDF関数はDescriptionというアノテーションが定義されています。xxxxという構文で表示される説明は、このアノテーションの情報を表示しているだけです。いうわけで、SpringFrameworkのClassPathScanningCandidateComponentProviderを使ってClassPath中のDescriptionアノテーションが定義してあるクラスを取得して情報を拾っているだけです。scanner.findCandidateComponents("");取得したBean定義を回して、リフレクション使ってAnnotation情報を取得します。nameをカンマで区切っているのは、Aliasがある場合はカンマ区切りで入っているからです。あとはdescから情報を普通に引っこ抜けます。HiveHiveのチケットを開いてBug報告をしてみたのでその手順をメモメモ。テストの方法とかも書いておきます。(チケットの内容はほとんどshiumachiさんに書いたもらったものですけどね(ノ∀`))shiumachiさん、丁寧に教えていただきましてありがとうございます。https://cwiki.apache.org/confluence/display/Hive/HowToContributeWikiにも書いてあるので、こちらを参考にすると良いと思います。trunkで再現するかの確認についてEclipseを使ってやる場合は、こちらのページが参考になると思います。今回は簡単な修正だったのでコンソール上だけで行いました。trunkを落としてきてビルド、Hiveを起動する手順を以下に書きました。設定ファイルを特に作っていないのでMetastoreはカレントディレクトリに作られます。MetastoreをMySQLに入れるところがーとかを修正する場合は、ちゃんとconfの下に設定ファイルを作って設定しましょう。./hive今回初めてgitを使いました。Hiveの規模であれば、--depthオプション無くてもいけます。svnの場合はwikiにある通りに、以下のようにソースを持って来ます。hive-trunk■ソースを修正したらテストをします。私のPCではテスト全部通すと4時間程度かかりました。全てのテストを実行する場合は以下のように実行します。テストが終わったらテストレポートも作ります。テストレポートはbuild/testディレクトリにjunit-noframes.htmlというファイルが作られます。このレポートファイルを見ると、何のテストが失敗したのかと、簡単な情報(例えばExceptionが出ているとか)がわかります。testreport個別にテストをする場合は、以下のようにします。qファイルはフルパスではなくファイル名を指定します。-Dtest.silent=falseなお指定したqueryのテストに対応する正解データは.q.outファイルです。上記の場合は、ql/src/test/results/clientpositive/timestamp_udf.q.outのファイルが正解データとなります。正解データを実行結果で上書きする事ができます。以下のコマンドで上書きできます(-Doverwrite=trueを追加)。-Dtest.silent=false私は今回上記のテストケースファイルに追加する形で対応しました。テストする時は、上記のように影響があるテストをピンポイントで実行して最後にテストを全部通すと良いと思います。全体テストは時間がかかるので、並列実行する方法があります。(直列のまま実行する場合は、寝る前に実行すれば良いと思うよ!!)テストに関する情報は、こちらのWikiのページのTestingの項目が参考になります。(パッチを投稿する場合)テストが通ったらパッチを作ります。Contributeのページに書いてあるとおり、以下のように作ります。パッチファイルはテキストファイルとして作った方がブラウザで見れるのでその方が良いです。browser.」とWikiに書いてありますし、shiumachiさんからもその方がいいよーとの事です。HIVE-xxxx.1.patch.txt■JIRAのチケットをOPENします。これを参考にすると良いよ!shiumachiさんの添削が載っているので、とっても参考になると思います。(githubのアカウントもこの時に作ったので、今度からちょこちょこ何かソースアップしていきます。)実際にOPENする方法は、まずはJIRAのアカウントを作ります。(アカウントの設定でLanguageを日本語に出来ますが、逆にわかりづらくなって発狂するのでEnglishのままのが良いです。(下の絵を参照)Issueの内容ですが、IssueTypeにはBugが設定されていると思うので、他の項目を入力していきます。いわゆるタイトルです。この項目は以下を参考にします。対象のコンポーネントを選択します。今回は「UDF」を選択しました。発生するバージョンを選択します。今回はHive0.8を選択しました。Trunkの場合は選択しないようです。選択されているチケットが少ない気がするのですが、リリースされているバージョンで発生するので、ちゃんと選択してみました。なんか書いている人が少ない。Hadoopのバージョンとか書くのかな・・。空欄にしちゃいました。チケットの内容を書きます。あとは空欄にしちゃいました。(ノ∀`)パッチを添付する場合は一度チケットを作ってから添付します。Filesを選択すると添付できます。実際に作ったチケットはこれです。HiveHadoopアドベントカレンダーでTimestampの機能について書いた時に見つけた不具合を調査してみました。自分の備忘録用にメモメモ。from_utc_timestampまたはto_utc_timestampをSELECT句に複数書くと値がおかしくなるというものです。正確には、1つ書いても壊れます。18:00:00おや、全部の値が変わってしまいました。'JST')を追加してみます。03:00:00SELECT句で書いたt1が全て同じ値になります。次に実装クラスを見てみます。org.apache.hadoop.hive.ql.udf.genericパッケージのGenericUDFFromUtcTimestampとGenericUDFToUtcTimestampです。GenericUDFToUtcTimestampはGenericUDFFromUtcTimestampを継承していて、フラグに応じてOffset値の正負を反転させているだけです。問題はGenericUDFFromUtcTimestampのapplyOffsetメソッドです。ソースを下に書きました。}行を評価中、timestamp変数は同じインスタンスを毎回返してきます。そのインスタンスに対してapplyOffsetでsetTimeしちゃってます。その行を評価中はt1は同じインスタンスを使い回してしまいます。SELECT句に書いたOffset値全てが計算された結果が出力されるわけです。1列評価→出力→1列評価→出力ではなく、全ての列を評価→出力なので、出力時には全て同じtimestampインスタンスを指すことになって、全て同じ値が表示されるわけです。(ここで言う全てはt1を参照している列という意味です)修正方法ですが、結局のところは同じインスタンスを指せないという事で、インスタンスを生成する必要が出てきます。いうわけで、手っ取り早く修正するのであればapplyOffsetを修正します。}(追記)上記のコードはダメでした。nano時間のところがそもそもバグっていて秒未満の値がずれます。以下のコードの方が良いです。}hiveをビルドしなおして再度実行してみます。18:00:00直りました。Hadoop、Hiveのコミュニティっていきなりチケットを開いてもいいのかな。MLとJIRAを漁って作法を調べよう。チケット開く前にパッチを置いておこう。Javaソースとテスト用のqファイル、q.outファイルのパッチは分離して2つに分けた方が良かったかな・・。Hivefluentの勉強会に参加したら、まわりがモヒカンばっかりで消毒されそうになったタムタムです。apacheもjsonとしてデータが飛んでいるとの事で、相性は悪くないよねーというわけでサンプルを作ってみました。(スライドを見ていた感じではこんな感じだったはず)まずサンプルデータを用意します。適当に100件ほど作りました。"exam3":46}....まずはデータをそのまま1つの列に入れます。今回はサンプルなのでPARTITIONは切っていません。raw_data;このJSONデータをテーブル化するクエリは以下のように書けます。(Hiveのマニュアルには、上記のようなクエリを書くなら下記のようなクエリを書きましょうねと書いてあります。exam3;json_tupleはstring型として返ってくるので、これを整数型にします。SELECT句でCastしているだけです。exam3;これをView化します。exam3;簡単な集計をしてみます。50.43集計できました。hive.optimize.ppd=false;」と設定するみたいです。https://issues.apache.org/jira/browse/HIVE-1056ちなみにJSON用のSerdeもあります。http://code.google.com/p/hive-json-serde/ぶっちゃけ、こっち使った方がスマートに書けますwというわけで、hiveはfluentとの相性も良さそうですね。Java本当は食べ物の写真とか載せたいんですけどね。この前やらかしちゃった事を備忘録としてメモメモ。Javaでは基本的にSerializableを実装していないと(Externalizableでもいいけど)、Objectをシリアライズできません。MemcachedにそのままObjectをまるっと保存する場合は、ObjectOutputStreamを介して保存する事が多いと思います。(MsgPackとかJSONICとかを使う方が良いかもしれませんが)。この前やらかしてしまったのは、JavaのListインターフェースにあるsubListで返ってくるリストはSerializableインターフェースを実装していないListなので、キャッシュに保存できないでエラーが出まくりでした。書くと語弊があるので正確に書くと、ArrayListとLinkedListはAbstractListを継承しており、subListの実装はAbstractListが持っています。AbstractList#subListの実装は、RandomAccessを実装しているクラスの場合はRandomAccessSubListを、実装していない場合はSubListのObjectを返します。RandomAccessSubListもSubListもSerializableは実装されていません。toIndex));}ちなみに、subListは要素をコピーして作っているわけでは無く、単純に元リストのラッパークラスのように振る舞っているだけなので、そこも注意なのです。subListで返ってきたリストに対して操作するとどうなるかのサンプルを書きました。Hiveタムタムです。書かせていただきます。それと、時々ログ解析飲み会というものをやっているという噂があるのですが、わたしも混ぜてください><さて、まずはじめに・・。ログが整形されているなんて都市伝説です。自分が作るアプリは最初からログ設計をして整形して出力しているのですが、世の中そんなものばかりではありません。Hiveで集計するためにはある程度書式が整っていないとスマートに処理できません。適当なスクリプトで処理するのも手ですが、もともと分散しないと処理できないほどの量なのに、それを分散環境で処理しないとか無いと思います・・。Streamingでログを処理すればいいよねーとなるわけです。用途はある程度限られてしまいますが実はHiveでも出来ます。以下のようなログがあるとします。(85.9,199.2,-590.6)さて、このファイルにはモンスターの討伐記録のログがあります。記録されており、まずはこの形式のログだけを抽出してテーブルに入れたいわけです。(ワールドとエリアはログファイルの単位なので記録はされていないです。)まずは元のgzログをtmp2テーブルに入れます。ログファイルはHDFS上にあります。パーティションを適当に切ります。idは適当なIDを入れて作業がかぶらないようにする用です。OracleのPLAN_TABLEみたいなイメージです。area='dungeon01');次にMap用のスクリプトを書きます。}}わざわざ配列に入れてjoinする必要なんてありませんよね。コメントを見やすくする関係でこう書きました。確認したい場合は、以下のようにやればスクリプトの確認はできます。-590.6試しにSELECTしてみます。-570.1(結果をダミーのものに書き換えるのめんどくさい・・・。本物出すわけにはいかないし・・。8集計できました(・ω・)ノTmpテーブルを経由しないといけないのがアレですが、externalなのでログの複製は行われないし、中間テーブル的な整形されたテーブルの実体も持たなくて良いのです。集計前にテーブルに1回入れる場合は普通に末尾にINSERT構文を書けばできます。いう方法もありますよと言うことで。今回はMapしか書いてませんが、Reduceもスクリプトで書くことができます。Hiveこんにちは、タムタムです。久しぶりに記事を書きます。Hadoopアドベントカレンダー2011の17日目という事で書かせていただきます。私のような底辺エンジニアでも集合論の知識のみで簡単にデータ集計処理が書けるのがHiveの良いところだと思います。試しに某ゲームのモンスター討伐のログを、数日分、全ワールド、Zoneエリア、モンスター単位で集計したら100秒くらいで結果が出ました。(その時はレコードが1億程度と少ないという事もありますが)※ちなみに私はマイニングエンジニアではありません。いうわけでHive0.8に関する事を書きたいと思います。Hive0.8ではBitmapインデックスやtimestamp型が追加されたというのが大きなトピックらしいです。新機能を試してみたいと思います。細かい構文が追加されているようなので、それもおいおい試してみたいと思います。今回はtimestamp型について書きます。ちなみに、まだリリースされていないのでソースを持ってきてビルドする必要があります。ビルドの方法は次の通りです。packagebuild/dist配下にパッケージが出来ていますので、build/distをHIVE_HOMEに設定してbin/hiveを実行します。0.8は12/16にリリースされてましたw今まで日付データをhiveで扱うにはstringとして保持してWHERE句にUDFで日付に戻して計算をするとか、bigintでunixtimeとして保持したりしていました。timestamp型についてまずはどんな操作ができるのか調べてみます。functions;の結果を0.7と0.8で比較し、0.8で追加されたUDFを列挙しました。(descriptionはコマンド打っても出てこなかったものがあるので書くのをやめましたw)UDFDescriptionewah_bitmapewah_bitmap_andewah_bitmap_emptyewah_bitmap_orfrom_utc_timestampmap_keysmap_valuesnamed_structtimestampto_utc_timestampまたJIRAのチケットによると、datetimeに関する様々なUDFがtimestampをサポートしたようです。以下のような操作ができます。サンプルデータを1件用意します。HH:mm:ss.fffffffffのみです。-5新しいUDFも試してみましょう。17:00:00うまく動いているように見えます。以下のクエリを発行すると正しい結果が得られません。09:00:00はどのTimeZoneの9時なのか?という事が気になると思います。UTC」という事で無かったことになっています。実際は上の結果を見る限り(castとか)TimeZone.getDefault()が使われているように見えます。(すいませんソース追っていません)。OracleVMの場合はVMプロパティのuser.timezoneで指定できますが、システムプロパティなので他に影響を及ぼしそうで怖いです。Javaのコードで確認したら似たような動作したので、たぶんDefaultのTimeZoneを使っていると思います。09:00:00").getTime());13247712000001324803600000個人的には、時間に関する型をサポートするならSimpleDateFormatの書式をtableの設定で出来ると嬉しいんですけどね。いうわけで、timestamp型に関する事を書いてみました。ネタが足りなければ列指向のRCFileとSequenceFileの性能の違いやRCFileをJavaののコードで作る方法あたりを書きたいと思います。PostgresMySQLはJDBCからアクセスする時に全件取得するのでバッチ処理が書きづらいという理由でPostgreSQLをインストールしてみました。(フェッチサイズをInteger.MIN_VALUEに設定すれば1件づつの取得になりますが、この間に他のトランザクション走らせることができないので。)(あれ・・・コネクションを2本使えばいいのでは・・?)インストールしたバージョンは8.4.2です。installDB初期化します。--pgdata=/lunar/data/postgres起動します。startスキーマを作ります。-W外部から接続できるように/lunar/data/postgres/pg_hba.confに設定を追加します。md5パスワードを設定しなおしました。'xxxxxxxx';他のホストから接続してみる。postgres手間はMySQLよりも1つ多いくらい。́・ω・)メモリ設定とかDISKのフラッシュ設定とかログ設定とか運用設定とか。JavaJavaのClassLoaderの話をちょっとだけ。意外にClassLoaderを知らない人が居るようです。説明をしますと、クラスローダーにはBootstrapクラスローダーやシステムクラスローダー、コンテキストクラスローダーがあります。(あと拡張クラスローダーですかね)。そんでもって、クラスローダーは親子関係を持っています。委譲モデルと言って、あるクラスローダーにクラスをロードする依頼があると、親に依頼を委譲します。最初に発見されたクラスが実際にロードされるわけです。子クラスローダーBこんなクラスローダーがあるとしてまだロードされていないクラスXをロードしようとした場合は次のように動作します。B.loadClass(X)Aに委譲Bootstrapに委譲BoostrapにXは存在しないAにXは存在しないBにXが存在するのでロードする。ちなみにClassLoader#findClassをオーバーライドして自前の処理で上書きしてしまえば、この委譲モデルを破壊する事ができます。́・ω・)JVMプロセス内においては異なるClassLoaderで読み込んだクラスは例え同じバイナリでも異なるクラスとして扱われます。ClassLoaderAによってロードされたクラスXと、ClassLoaderBによってロードされたクラスXは別物です。※クラスAとBが親子関係を持っていて、AがXをロードしている時にBでロードしても委譲モデルでAが既にロードしてあるXを使うので、こういう場合は同じ定義を指します。TomcatのWebApps1とWebApps2の関係を想像すると理解しやすいと思います。この特性を生かすとリロード処理が実現できるわけです。ClassLoaderの細かい話はDeveloperWorksの記事が丁寧なのでそちらを参照した方が良いです。今回はTomcatにも実装されているリロード処理のサンプルを作ってみたいと思います。TomcatのドキュメントにTomcatのClassLoaderの戦略が書いてあるのでそれを参考にすると分かりやすいと思います。RPCサーバやスケジューラーを考えます。これらを設計する時には大きく二つに分けることができ、RPCサーバではサーバ本体と各命令、スケジューラーでも本体と各タスクという感じです。Tomcatの場合はServletエンジンとビジネスロジックを書いたServlet。(ビジネスロジックはServletに書くものではありませんけどね。)RPCの命令、スケジューラーのタスク、ServletコンテナのServletは抽象化する事ができ、インターフェースを切ることが多いです。(HttpServletとかね。)擬似コードだとこんな感じですね。}}このMyServerとITaskを本体側のClassLoaderに、ITaskを実装したクラスを別のClassLoaderに読み込ませます。本体はCLASSPATHを指定してシステムクラスローダーに読み込ませます。(TomcatはBoostrap用のクラスを挟んでいますけどね。)タスクは独自のクラスローダーをインスタンス化(このオブジェクトをc1とする)して(URLClassLoaderを直接でも良い)、そのClassLoaderを使ってクラス定義を読み込ませます。C言語だとdlopenみたいなイメージです。異なるクラスローダーから読み込んだクラスは別のクラスになるので、リロードしたい場合はClassLoaderをもう1回インスタンス化(c2)してあげればいいのです。文章だけで説明してもアレなので簡単なサンプルを書いてみました。Thread#setContextClassLoaderを使うともっと簡単に書けると思います。サンプルの内容は定期的にタスクを実行するだけのものです。Reload処理はJMX経由で行うようにしました。Eclipse上で作る時はタスククラスは別プロジェクトで作るのが良いです。同じプロジェクトに入れてしまうとシステムクラスローダーによってタスクもロードされてしまうので。Sleepの代わりにSemaphoreを使っている理由はsleepの場合Future#cancelで割り込みが発生しなかったからです。Semaphoreだと割り込みが入ってすぐに終了できます。tasklist.propertiesに登録したいタスクのクラス名を書く必要があります。こんな事をしなくてもLunarClassLoaderに手を加えて特定のインターフェースを実装しているクラスを検索(列挙)すれば良いだけです。今回はそこまで余力がありませんでした。タスク用のクラスパスはソースに直書きしています。自分の環境に合わせて修正してください。VMの引数に-Dhogehogeを指定してシステムプロパティとして読み込むのが一般的な方法かと思います。}}シングルインスタンスモデルにするか、プロトタイプモデルにするか迷ったのでclsMapとかでClass定義を保持しているわけです。今回はシングルインスタンスモデルにしたので実はclsMapは必要ありません。reload();}ここからタスクです。Eclipse上では別プロジェクトにした方が良いです。今回は2つのクラスを登録します。}}クラスパスのルートにtasklist.propertiesを作成します。at.orz.lunar.task.SampleTask1at.orz.lunar.task.SampleTask2実行した後にSampleTask2の内容を変更(★を★★★★★に変更)した後にjconsoleからreloadを呼び出した結果が↓です。́)そしてリ新しいクラスの内容が読み込まれているのも確認できます。※途中から書くのが面倒になったのがソースからわかっちゃうと思いますが、サンプルなので気にしない(・ε・)ただし、このような処理はちょっとミスするとPermGenが解放されずにOutOfMemoryErrorを引き起こす原因になりやすいので気をつけましょー。(IBMのVM使えばいいじゃんとかそういう野暮な事は言わないの。SolrSolr1.4ではとあるURLにアクセスする事でバックアップ(スナップショット)を取れるようになっています。http://wiki.apache.org/solr/SolrReplication↑のSolrのWikiにもあるようにReplicationの機能をONにする必要がありますが、スレーブの設定をしなくても動作するのでマスタのみでもきちんと動作します。以下のURLにアクセスするとデータディレクトリと同列に「snapshot.日時」というディレクトリを作成します。http://master_host:port/solr/replication?command=backupこの時、日付はyyyyMMddHHmmssという書式が指定されているはずなのですが、実はHHがhhになっており、午後の18時に実行しても18にならずに06になってしまいます。SnapShooterというクラスのDATE_FMTの指定を見ると思いっきり小文字で指定されています。