سؤال

لنفترض أن لديك نموذجين، المستخدم والمدينة، مرتبطين بالنموذج الثالث 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 و user هي متغيرات مثيل لفئة المدينة والمستخدم، تسمح بذلك city.users, city.city_permissions, user.cities, ، و user.city_permissions للجميع أداء جيد على قدم المساواة؟

هل كانت مفيدة؟

المحلول

وتبدو جيدة بالنسبة لي.

ووينضم إنشاء يجب أن يكون فقط على أي معرفات PK الجداول كيان، أو على معرفات FK في الجدول الانضمام - وكلاهما المؤشرات

وربما سيكون من الجيد أن ننظر إلى SQL أكتيفيريكورد ولدت ومقارنتها ضد الفهارس.

ويمكن اعتمادا على ما كنت قاعدة بيانات عليك ثم تشغيل هذا SQL من خلال خطة اشرح (أو أيا كان وجود أداة، أنا أفكر أوراكل هنا)

لتبسيط التعليمات البرمجية الخاصة بك، هل يمكن أن ننظر في استخدام has_and_belongs_to_many كذلك. ومن شأن ذلك أن تتيح لك الحصول على التخلص من وجوه CityPermission (إلا إذا كنت تريد استخدام ذلك لتخزين البيانات في حد ذاته)

نصائح أخرى

هنا هو SQL الذي ينشئه ActiveRecord 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 |             |
+----+-------------+------------------+--------+---------------------------------------------------------------------+-----------------------------------+---------+-------------------------------------------------+------+-------------+

وهذا هو SQL الذي ينشئه ActiveRecord 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

تتم قراءة صف واحد من هذا الجدول لكل مجموعة من الصفوف من الجداول السابقة.بخلاف أنواع النظام والثوابت، يعد هذا أفضل نوع ربط ممكن.يتم استخدامه عندما يتم استخدام كافة أجزاء الفهرس بواسطة الصلة ويكون الفهرس عبارة عن مفتاح أساسي أو فهرس فريد.

المرجع

تتم قراءة كافة الصفوف ذات قيم الفهرس المطابقة من هذا الجدول لكل مجموعة من الصفوف من الجداول السابقة.يتم استخدام ref إذا كانت الصلة تستخدم فقط بادئة في أقصى يسار المفتاح أو إذا لم يكن المفتاح مفتاحًا أساسيًا أو فهرسًا فريدًا (بمعنى آخر، إذا لم تتمكن الصلة من تحديد صف واحد استنادًا إلى قيمة المفتاح).إذا كان المفتاح المستخدم يطابق بضعة صفوف فقط، فهذا نوع ربط جيد.

scroll top