8

User と City の 2 つのモデルがあり、3 番目のモデル CityPermission で結合されているとします。

class CityPermission < ActiveRecord::Base
  belongs_to :city
  belongs_to :user
end

class City < ActiveRecord::Base
  has_many :city_permissions
  has_many :users, :through => :city_permissions
end

class User < ActiveRecord::Base
  has_many :city_permissions
  has_many :cities, :through => :city_permissions
end

現在、次の移行コード スニペットを使用して、結合テーブルとテーブルのインデックスを作成しています。

create_table :city_permissions do |t|
      t.integer :user_id, :city_id
      t.other_fields ...
end

add_index(:city_permissions, :user_id)
add_index(:city_permissions, :city_id)

これらは作成するのに最適なインデックスですか? これらのインデックスを使用すると、結合テーブルを介して前後にすばやくアクセスしたり、テーブル自体内ですばやく検索したりできますか、それとも他のより良い方法はありますか? これを少し別の言い方をすると、与えられたこれらのインデックスは、cityクラスuserCity と User のインスタンス変数でありcity.users、 、city.city_permissionsuser.cities、およびuser.city_permissionsがすべて同じようにうまく機能するでしょうか?

4

2 に答える 2

4

は、私にはよく見えますよ。

生成された結合は、エンティティ テーブルの PK ID、または結合テーブルの FK ID (どちらもインデックス) のいずれかにある必要があります。

おそらく、生成された ActiveRecord SQL を見て、それをインデックスと比較するとよいでしょう。

使用しているデータベースに応じて、Explain プランを介してその SQL を実行できます (または、存在するツールは何でも、ここでは Oracle と考えています)。

コードを簡素化するために、 using も検討できますhas_and_belongs_to_many。これにより、CityPermission オブジェクトを取り除くことができます (それを使用してデータをそれ自体に保存する場合を除きます)。

于 2008-10-21T22:40:47.747 に答える
1

ActiveRecord が に対して生成する SQL は次のuser.citiesとおりです。

SELECT `cities`.* FROM `cities` INNER JOIN city_permissions ON (cities.id = city_permissions.city_id) WHERE (city_permissions.user_id = 1 )

以下の結果を説明してください:

+----+-------------+------------------+--------+---------------------------------------------------------------------+-----------------------------------+---------+-------------------------------------------------+------+-------------+
| id | select_type | table            | type   | possible_keys                                                       | key                               | key_len | ref                                             | rows | Extra       |
+----+-------------+------------------+--------+---------------------------------------------------------------------+-----------------------------------+---------+-------------------------------------------------+------+-------------+
|  1 | SIMPLE      | city_permissions | ref    | index_city_permissions_on_user_id,index_city_permissions_on_city_id | index_city_permissions_on_user_id | 5       | const                                           |    1 | Using where |
|  1 | SIMPLE      | cities           | eq_ref | PRIMARY                                                             | PRIMARY                           | 4       | barhopolis_development.city_permissions.city_id |    1 |             |
+----+-------------+------------------+--------+---------------------------------------------------------------------+-----------------------------------+---------+-------------------------------------------------+------+-------------+

ActiveRecord が生成する SQL は次のuser.city_permissionsとおりです。

SELECT * FROM `city_permissions` WHERE (`city_permissions`.user_id = 1)

そのクエリの EXPLAIN の結果:

+----+-------------+------------------+------+-----------------------------------+-----------------------------------+---------+-------+------+-------------+
| id | select_type | table            | type | possible_keys                     | key                               | key_len | ref   | rows | Extra       |
+----+-------------+------------------+------+-----------------------------------+-----------------------------------+---------+-------+------+-------------+
|  1 | SIMPLE      | city_permissions | ref  | index_city_permissions_on_user_id | index_city_permissions_on_user_id | 5       | const |    1 | Using where |
+----+-------------+------------------+------+-----------------------------------+-----------------------------------+---------+-------+------+-------------+

実際に正しく動作しているようです。MySQLマニュアルから:

eq_ref

前のテーブルの行の組み合わせごとに、このテーブルから 1 行が読み取られます。system 型と const 型以外では、これが最適な結合型です。これは、インデックスのすべての部分が結合によって使用され、インデックスが PRIMARY KEY または UNIQUE インデックスである場合に使用されます。

参照

前のテーブルの行の組み合わせごとに、一致するインデックス値を持つすべての行がこのテーブルから読み取られます。結合がキーの左端のプレフィックスのみを使用する場合、またはキーが PRIMARY KEY または UNIQUE インデックスでない場合 (つまり、結合がキー値に基づいて単一の行を選択できない場合)、ref が使用されます。使用されるキーが数行しか一致しない場合、これは適切な結合タイプです。

于 2008-10-21T22:42:35.450 に答える