2008年6月14日土曜日

Many-to-many JOIN

Many-to-many JOIN のサンプル、Intersection Table にあたるものに Reference Property だけの db.Model を作成することで対応。
back-references を使っているので注意
def books()  などは必須ではないと思う。(当初、かえってこれで混乱してしまった)













Google App Engine: [A Better] Many-to-many JOIN
http://blog.arbingersys.com/2008/04/google-app-engine-better-many-to-many.html

ER-Modeling with Google App Engine (updated)
http://daily.profeth.de/search/label/entity%20relationship%20model

Google App Engine 入門6 検索件数
http://webdba.blogspot.com/2008/04/google-app-engine6.html

None による条件検索

まず
 select * from Kawase where entry_date = None 
はエラーとなる。
必ず、バインド変数のように指定しなければならない。

entity = db.GqlQuery("select * from Kawase where stock = :1", None)
for e in entity:
print e.entry_date, e.stock
 
しかし、これで Kawase の stock = None の値がすべて検索できるわけではない。
以下の検索で None となって、検索結果が返ってきているが、上の検索のリストにな該当レコードがない。

entity = db.GqlQuery("select * from Kawase where entry_date = :1 ", e1 )
for e in entity:
print e.entry_date, e.stock
 
原因:
 後から Property を追加したような場合、この Property を None で更新した場合、
「"select * from Kawase where stock = :1", None 」に該当するが、そうでないレコード(entities)は値が未登録であっても、この検索には該当しないようである。( SDK 1.1.0)

google/appengine/ext/admin/__init__.py
からしても、Google の Datastore は実際のデータを get して、解析してみなければ、そのデータの構造がわからない。 RDBでいうところの dictionary テーブルのようなものは存在しない。存在しないものを検索することはできない。
つまり、ある db.Model はどんな、 Property から構成されているかは、事前にはわからない。検索してはじめてわかる。

Docs > Datastore API > Entities and Models の以下の意味がようやく少し解ってきた。
Unlike relational databases, the App Engine datastore does not require that all entities of a given kind have the same properties. The application can specify and enforce its data models using the model API.

2008年6月13日金曜日

2つのdb.Modelの結合、そして back-references とは?

2つのdb.Modelの結合は Reference Property がないと遅い。

Reference Propertyを設定しても、ここに値(Key)が登録されていない場合、結合の際に以下のエラーとなる。(要エラー処理)
AttributeError: 'NoneType' object has no attribute 'entry_date'

1:1 の対応になるのであれば、大きな表形式にするのがやはり正しい。
ただし、1行ごとに fetch しながらの更新には時間がかかる。 
200レコード程度の処理に15分かかった。(Windows による開発環境にて)
後から Reference Property にしろ、実際に追加したいデータにしろ、更新処理によりつけ加えるのには非常に時間がかかる。これは覚悟しておく必要がある。

from datetime import *
import datetime
from google.appengine.ext import db

class Stock(db.Model):
nikkei_ave = db.FloatProperty()
entry_date = db.DateTimeProperty()
modified = db.DateTimeProperty(auto_now=True)
usd_jpy = db.FloatProperty()
class Kawase(db.Model):
author = db.UserProperty()
usd_jpy = db.FloatProperty()
entry_date = db.DateTimeProperty()
modified = db.DateTimeProperty(auto_now=True)
stock = db.ReferenceProperty(Stock)

start_time = datetime.datetime.today()
e1 = datetime.datetime.strptime( "2003-08-01" ,'%Y-%m-%d')
e2 = datetime.datetime.strptime( "2003-08-22" ,'%Y-%m-%d')

kawases = db.GqlQuery("SELECT * FROM Kawase where entry_date >=:1 and entry_date <:2 ", e1,e2 )
for kawase in kawases:
stocks = db.GqlQuery("select * from Stock where entry_date = :1", kawase.entry_date )
for stock in stocks:
kawase.stock = stock.key()
kawase.put()
end_time = datetime.datetime.today()
print end_time - start_time

Kawase(db.Model) 側に Stock を参照するための Reference Property を追加し、ここに対応する Stock(db.Model) の Key を登録しておくと、 Kawase 側から簡単に Stock側の値を結合することができる。
Reference Property が抜けている(未登録)とエラーになるので注意。
entity = db.GqlQuery("select * from Kawase")
for e in entity:
try:
print e.entry_date,e.usd_jpy, e.stock. entry_date, e.stock.nikkei_ave
except AttributeError:
print e.entry_date,e.usd_jpy, None,None

Kawase(db.Model) 側に Stock を参照するための Reference Property を追加し、ここに対応する Stock(db.Model) の Key を登録しておくと、 Kawase 側から簡単に Stock側の値を結合することができる。
Reference Property が抜けている(未登録)とエラーになるので注意。
entity = db.GqlQuery("select * from Kawase")
for e in entity:
try:
print e.entry_date,e.usd_jpy, e.stock. entry_date, e.stock.nikkei_ave
except AttributeError:
print e.entry_date,e.usd_jpy, None,None

Stock 側からの結合は Stock 1 レコード(entity)対して、複数 Kawase レコードが対応する可能性があるので2段階のループになる。
entity = db.GqlQuery("select * from Stock limit 10")
for e in entity:
for k in e.kawase_set:
print e.entry_date,e.nikkei_ave, k.entry_date, k.usd_jpy

Stock Kawase entry_datejoin するため、Kawase 側に ReferenceProperty を作成した。Master-Detail でいうと Stock が Master側になるわけだが、これからDetail側を参照するために自動的に kawase_set という擬似的なものが作成される。
確かにこれを back-references と呼ぶのは仕組みがわかってくると、適切なように思える。

また、back-references は遅いので注意。
上記の10件の join で 22秒もかかった。(SDKにて。 Kawase 1,935件、Stock 1,842件)

これは原則として Master側は1画面に1レコードとした使い方としないといけない。

Docs > Datastore API > Entities and Models で
ReferenceProperty has another handy feature: back-references. When a model has a ReferenceProperty to another model, each referenced entity gets a property whose value is a Query that returns all of the entities of the first model that refer to it.
と説明されている。

2008年6月11日水曜日

グーグルデータセンターの内側

ここまでくるとサーバの保守は生命工学にせまる、最先端の領域となる。

http://japan.cnet.com/special/story/0,2000056049,20374847,00.htm

Googleのような規模でサーバを運営するには、マシンを消耗品として扱う必要がある。サーバメーカーはハイエンドマシンが故障に強いことを誇りにしているが、Googleはフォールトトレラントソフトウェアに資金を投入する方を選んでいる。

やっかいな慣らし運転
各クラスタでは1年目に、1000件の個々のマシン故障が発生するのが一般的だ。ハードドライブ故障は数千件起こる。

Googleは本当に心からマルチコアマシンを気に入っている。われわれにとって、マルチコアマシンは、相互接続に優れたたくさんの小型マシンのようなもので、比較的使いやすい

シングルスレッドのパフォーマンスはGoogleにはまったく重要ではない。Googleには並列化可能な問題がたくさんある

Google成功の秘密
Dean氏は、Googleのソフトウェアの3つの中核となる要素、すなわち「GFS(Google File System)」「BigTable」「MapReduce」アルゴリズムについて説明した。

マシン故障はすべてGFSシステム、少なくともストレージレベルで処理される

すべてのデータに構造を提供するためにGoogleはBigTableを使用している。
Oracle、IBMといったメーカーの市販のデータベースは、 Googleには適さない。
1つには、Googleが要求する規模での運営ができないからだが、
 たとえ可能だとしても、費用がかかりすぎる

Bigtable is a distributed storage system for managing structured data.
MapReduce is a programming model and an associated implementation
 for processing and generating large data sets.

MapReduceは、Googleの持つデータを実質的に活用できるようにするもので、最初のバージョンは2003年に作成された。たとえば、 MapReduceでは、特定の単語がGoogleの検索インデックスに登場した回数、ある単語が表示されているウェブページのリスト、特定のウェブサイ トにリンクしているすべてのウェブサイトのリストを確認できる。

フォールトトレラントソフトウェア
言うまでもなく、MapReduceはGFSと同様に、サーバの問題を回避するために開発されたものである。

以前、1800台のサーバで構成されるクラスタでの保守作業中に、本格的なMapReduceの信頼性のテストが行われた。作業担当者が一度に80台のマ シンの電源を抜いたところ、残りの1720台のマシンがその穴を埋めた。「動作速度は少し落ちたが、すべて終了した」とDean氏は語る。

次世代データセンターの今後の課題
ほとんどの企業は、ジョブをサーバから別のサーバにスムーズに移動する方法を考えているが、Googleの課題はけたが違う。Googleはジョブをデータセンターから別のデータセンターに移動できるようにしたいと考えている。しかも自動的にだ。


2008年6月6日金曜日

GAE 一括更新

SDK 1.10 から Gql でも  !=  がサポートされたが、これは

<=, >= などと同じ扱いなので、 日付で <=  を使うと、  他の条件で !=  が使えなくなる。

また、 order by などの sort  も <=  を利用した場合、その  property に限られる。

# RDBMS に比較するといろいろ制約があるが、データが溜まった後での
# 変な苦労からは開放されるか。

検索結果をまた絞ることもできるが、 key() まで対応するのは...。
key は不要で、 referece からみの関連する model がないのであれば対応可能。

結局、property を追加し batch でデータ更新することで対応。
バッチの更新は動作したが、 alter table add column などしないで、
model の定義を書き換えるだけで、
property を追加することができるのはいいが、どうもデータが蓄積された後、
追加したところは不安定な様子で、本体での更新処理が なぜがうまくいかない。

rr = db.GqlQuery("select * from Blog ")

for r in rr:
  print r.title,r.list_mode, r.open_mode
  r.list_mode = '0'
  r.put()

#db.put(rr)
-----

blogs = []
for b in blogs_tmp:
if b.category <> category:
blogs.append({
# key() : b.key(),
'author' : b.author,
'title' : b.title,
'content' : b.content,
'category' : b.category,
})

2008年6月4日水曜日

GAE でSpreadsheets Data API にトライ

C:\Python25\Lib\site-packages\gdata\atom
C:\Python25\Lib\site-packages\gdata\gdata
を プロジェクトフォルダに copy して import はできて当然だが、
やはり gd_client.ProgrammaticLogin() あたりで
http のエラーとなる。


Traceback (most recent call last):
File "C:\Program Files\Google\google_appengine\google\appengine\ext\webapp\__init__.py", line 499, in __call__
handler.get(*groups)
File "C:\google\helloworld\helloworld0.py", line 18, in get
gd_client.ProgrammaticLogin()
File "C:\google\helloworld\gdata\service.py", line 301, in ProgrammaticLogin
content_type='application/x-www-form-urlencoded')
File "C:\google\helloworld\atom\service.py", line 316, in HttpRequest
connection.endheaders()
File "C:\Python25\lib\httplib.py", line 860, in endheaders
self._send_output()
File "C:\Python25\lib\httplib.py", line 732, in _send_output
self.send(msg)
File "C:\Python25\lib\httplib.py", line 699, in send
self.connect()
File "C:\Python25\lib\httplib.py", line 1133, in connect
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
AttributeError: 'module' object has no attribute 'socket'

2008年6月3日火曜日

Google Spreadsheets Data API

この概要は表示できません。投稿を閲覧するには ここをクリック してください。

Swift UI チュートリアル Loading watchOS が終わらない?

Loading watchOS が終わらない? ディスク容量の残量が少ないので不要なシュミレーターを削除したとこころ watchOSのものが全部なくなってしまっていた。 WatchOS を削除して再度インストールしても復活せず。 Create a new simulator で ...