2012-10-31 8 views
5

私はSQLAlchemy、データベースシャーディング、UUIDsに関する質問があります。SQLAlchemy、UUIDs、Sharding、およびAUTO_INCREMENT主キー...それらを連動させる方法?

私は現在、私は、フォームのテーブルを持っているMySQLを使用しています:

CREATE TABLE foo (
    added_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, 
    id BINARY(16) NOT NULL, 
    ... other stuff ... 
    UNIQUE KEY(id) 
); 

このテーブルにはほとんど背景。私は 'added_id'を気にしません。挿入されたアイテムがディスク上に一緒にクラスタ化されていることを確認するためだけに使用しています(B-TreeはMySQLのテーブルのインデックスに使用されているため、 'id'カラムにはUUIDのバイナリ表現が含まれています。これは実際に気にかけているカラムで、他のすべてのものがこのIDを参照しています。 UUIDはランダムなので、B-Treeを作成してテーブルのインデックスを作成すると、恐ろしいIO特性(少なくともこれは他のところで言われていることです)があるため、UUIDを主キーにしたくありません。また、UUID1には、IDが「順次」の順番で生成されるようにするためのタイムスタンプが含まれていますが、IDにMACアドレスを含めることで、避けたいものになります。したがって、私はUUID4を使用したいと思います。

これで、SQLAlchemyの部分に移動しました。 SQLAlchemyのでは1は次のような何かを行うことによって、上記の表のための彼らのORMを使用してモデルを定義することができます。

# The SQL Alchemy ORM base class 
Base = declerative_base() 

# The model for table 'foo' 
class Foo(Base): 
    __table__ = 'foo' 
    add_id = Column(Integer, primary_key=True, nullable=False) 
    id = Column(Binary, index=True, unique=True, nullable=False) 
    ... 

繰り返しますが、これは基本的に上記のSQLと同じです。

そして今質問します。このデータベースが2つ(またはそれ以上)の別々のデータベースに分割(水平方向に分割)されるとしましょう。さて、(削除されていないと仮定して)これらのデータベースのそれぞれは、テーブルfooに1、2、3などのadded_idを持つレコードを持ちます。 SQLAlchemyはセッションを使用して、それぞれのオブジェクトがプライマリキーだけで識別されるように作業しているオブジェクトを管理しているので、2つのFooオブジェクトから2つのFooオブジェクトにアクセスしようとする可能性があるようです同じadded_idを持つシャードは管理対象セッションで何らかの競合を引き起こします。

この問題を抱えている人はいますか?あなたはそれを解決するために何をしましたか?あるいは、おそらく、SQLAlchemyのドキュメントから何かが見つからないことがあります。しかし、SQLAlchemyのダウンロード(examples/sharding/attribute_shard.py)で提供されているシャーディングの例を見ると、データベースシャードの1つをIDジェネレータとして指定することで、この問題を解決することができます。 INSERTSはIDを取得するためにその単一のデータベースに対抗しなければなりません。また、UUIDを主キーとして設定し、added_idを使用してディスク上にデータをクラスタ化する方法がありますか?(UUIDの使用については言及していますが、インデックスのパフォーマンス上の問題を引き起こすとも言えます)

MySQLで可能でない場合、Postgresのような別のDBで可能でしょうか?

ありがとうございます。

--- UPDATE ---- 私はこの質問に受け取った帯域外の回答を追加したいだけです。次の文章は、私が書いたものではなく、誰かがそれを見つけた場合に備えてここに入れたいだけです。

MySQLと自動インクリメントキーの状況を避ける最も簡単な方法は、データベースごとに異なる自動インクリメントオフセットを使用することです。:

ALTER TABLE foo AUTO_INCREMENT = 100000;

各シャードの設定方法に注意する必要があり、使用するシャードの総数を少し計画する必要があります。

クラスタ化インデックスに非主キーを使用するようにMySQLに納得させる方法はありません。 SQLAlchemyを使用してデータベーススキーマを管理することに気にしない場合は、SQLAlchemyスキーマのUUIDをプライマリキーとして設定し、実際のテーブルのadd_idをpkのままにしておきます。

また、行IDを維持するために外部サーバー(例:redis)を使用する代わりの方法もあります。

答えて

5

はい、あなたは、Columnオブジェクトのリストまたは単一列である「PRIMARY_KEY」マッパー引数を、使用してマッピングの目的のために主キーとしてテーブルのカラムのいずれかを指定できます。

Base = declarative_base() 

# The model for table 'foo' 
class Foo(Base): 
    __table__ = 'foo' 
    add_id = Column(Integer, primary_key=True, nullable=False) 
    id = Column(Binary, index=True, unique=True, nullable=False) 

    __mapper_args__ = {'primary_key': id} 

上記では、SQLAlchemy Coreは "add_id"を "autoincrement"列として扱いますが、マッパーはほとんど関心がありません。代わりに、 "id"をオブジェクトの "同一性" 。

詳細については、documentation for mapper()を参照してください。

+0

ありがとうございます。 – prschmid

関連する問題