2014-01-06 13 views
5

複数のテーブルを使用するカスタマイズされたリレーションを作成しようとしています。このリレーションは、最初のテーブルのキーを使用して他のテーブルに結合する必要がありません。Yii複数のテーブルの1つのリレーション

各テーブルには同じ列があります。

ので、話は始めましょう:

私はオンライン戦略ベースのゲームを開発しています。

私は大きなテーブル(30.000.000行)を持っていて、100個の小さなテーブル(各テーブルの300.000行)でそのテーブルを分割しています。

アクションは村内で行われます。

村の詳細はvillageテーブルに保存されています。

各村は大陸内に位置しているので、村に属する大陸を私に与えるkという数字があります。

村のテーブルには、次のカラムがあります

ID - p.k. 地図上のx - x位置 地図上のy - y位置 k - f.k.大陸id 名前 user_id f.k. ポイント

私は100の大陸を持っているので、私は100の新しい小さなテーブルを持っています。

私はすべての建物の詳細を保存するテーブルもあります。

建物の詳細は、テーブルに保存されていました。

元のテーブルから私は今やvillage_building_k1,village_building_k2、...、village_building_k100を持っています。

village_building_k...表は次のカラムがあります

ID - p.k. village_id - f.k. building_id - f.k.

ここで、villageモデルからvillage_building_kXモデルにジャンプする関係を作成しようとしていますが、必要なときにXが変更されるはずです。

モデルvillagekの値を使用すると、参加する必要があるテーブルの名前がわかります。

K = 2の場合、私は連結

public function tableName() { 
     return 'village_building_k' . self::$k; 
    } 

public function relations() { 
     return array(
      'relation_village_building' => array(self::HAS_MANY, 'VillageBuildingKXSlaveM', 'village_id'), 
     ); 
    } 

$model_village->relation_village_building->building_id

答えて

3

私はいくつかの共有データベースを追加する必要があると思います。あなたの大きなデータベースのために、あなたのフレームワークでそれを管理することはできません。管理データベース用の共有データベースを試してみてください。また、あなたはデータベースを管理するためのmysqlクラスタを試すことができますFollow this linkthisこれはあなたの役に立つかもしれません。 1つのフレームワークは、コードやデータベースなどのサポート環境で機能を操作できるように、いくつかの関数セットであることを覚えておいてください。

5

を使用してvillage_building_k2villageからジャンプする必要があるあなたは、フレームワークレベルでこの問題を解決する必要があること、よろしいですか?私はここに何かを使用することを提案しますhttp://en.wikipedia.org/wiki/Shard_(database_architecture)

2

実際には、いくつかのグローバルパラメータから、例えばセッションからデータベース名を渡すことができます。

public function tableName() 
{ 
    return 'village_building_k' . Yii::app()->session['table']; 
} 

問題は、あなたのゲーマーのためのセッションを長時間保存することです。多くのユーザーがいる場合は問題になります。

同じ構造のテーブルが少ない場合は、おそらくデータベースアーキテクチャが間違っていると思われます。それがシャーディングであった場合は、これをARに変更する必要があります。

yiiとshardingの主な問題は、__construct()のARがgetMetaData()を呼び出してテーブルスキーマを取得するため、そのレベルでテーブル名が必要なことです。

解決方法をフォーラムで検索しても、個人的に英語に関する良い記事が見つかりませんでした。ここでは、YiiとRedis hereによる水平シャーディングの実現についての記事があります。ロシア語ですが、少なくともいくつかのコードを見ることができます。

そして、30.000.000のテーブルは、mysqlの中でさえ正しく動作するなら、大丈夫です。

+0

拡張機能のために30ミルそれは50ミルまで行く –

+2

それはいいです。あなたはこのテーブルに大きなデータを持っていないので、インデックスを付けることができ、高速になります。また、パーティション化を見て、シャーディングではなく、実際にパーティション化していました。この機能はmysql(またはあなたが使っているもの)にあります。すべての大陸のテーブルを100個作成してください。 1つまたは2つのパーティションの範囲での選択は非常に高速ですが、多くのパーティションから選択を避けてください。選択肢のインデックステストスピードを作成した後、それらの中には速度が遅くなるものがあります。ジョイン、GROUP BY、ORの多く、LIKE演算子を避けてください。 – ineersa

+0

また、ARをDAOに変更する必要があります。その方法は速く、メモリ消費も少なくて済みます。 AR - SELECT COUNT(*)クエリを再作成するか、dataProviderのtotalItemCountを設定します(例:フルテーブルの説明など)。インデックスによる一括挿入/削除は避けてください。これであなたはうまくいくはずです。私のDBはすでに200億に成長しました。それは大丈夫です。 – ineersa

関連する問題