Rails v. 5.2.4
ActiveRecord v5.2.4.3
У меня есть приложение Rails с базой данных MySQL, и мое приложение имеет модель Skill и модель SkillAdjacency. Модель SkillAdjacency имеет следующие атрибуты:
requested_skill_id, table_name: 'Skill'
adjacent_skill_id, table_name: 'Skill'
score, integer
SkillAdjacencies используются для определения того, насколько «похожи» два экземпляра Skill друг на друга.
Одно из ограничений приложения заключается в том, что вы можете Я не создаю более одного экземпляра SkillAdjacency для каждой комбинации required_skill и neighbour_skill, и я планирую обеспечить это как с помощью проверок ActiveModel, так и с помощью составного индекса, который использует ограничение уникальности. Пока у меня есть следующее:
add_index :skill_adjacencies, [:requested_skill_id, :adjacent_skill_id], unique: true, name: 'index_adjacencies_on_requested_then_adjacent', using: :btree
Однако я знаю, что порядок, в котором объявляются составные столбцы, важен, поэтому я рассматриваю возможность добавления этого 2-го составного индекса для учета другого возможного порядка :
add_index :skill_adjacencies, [:adjacent_skill_id, :requested_skill_id], unique: true, name: 'index_adjacencies_on_adjacent_then_requested', using: :btree
Но поскольку запись в индекс не бесплатна, я хочу добавить второй индекс только в том случае, если это действительно приведет к повышению производительности. Проблема в том, будет ли этот второй индекс полезным или нет, зависит от того, будет ли ActiveRecord начинаться с adjacent_skill_id
или requested_skill_id
при поиске составного индекса для поиска.
Как я могу определить, в каком порядке ActiveRecord использует? Он просто использует тот же порядок, который указан в запросе? Например, если я запрашиваю SkillAdjacency.where(requested_skill: Skill.last, adjacent_skill: Skill.first)
, всегда ли он будет искать составной индекс, состоящий из requested_skill
1-го и adjacent_skill
2-го? Если это так, должен ли я покрыть все свои базы, создав этот дополнительный составной индекс? указано в запросе?
EDIT:
Я запустил EXPLAIN
и увидел следующее:
irb(main):013:0> SkillAdjacency.where(requested_skill_id: 1, adjacent_skill_id: 200).explain
SkillAdjacency Load (0.3ms) SELECT `skill_adjacencies`.* FROM `skill_adjacencies` WHERE `skill_adjacencies`.`requested_skill_id` = 1 AND `skill_adjacencies`.`adjacent_skill_id` = 200
=> EXPLAIN for: SELECT `skill_adjacencies`.* FROM `skill_adjacencies` WHERE `skill_adjacencies`.`requested_skill_id` = 1 AND `skill_adjacencies`.`adjacent_skill_id` = 200
+----+-------------+-------------------+------------+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------+---------+-------------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------------------+------------+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------+---------+-------------+------+----------+-------+
| 1 | SIMPLE | skill_adjacencies | NULL | const | index_adjacencies_on_requested_then_adjacent,index_adjacencies_on_adjacent_then_requested,index_skill_adjacencies_on_requested_skill_id,index_skill_adjacencies_on_adjacent_skill_id | index_adjacencies_on_requested_then_adjacent | 10 | const,const | 1 | 100.0 | NULL |
+----+-------------+-------------------+------------+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------+---------+-------------+------+----------+-------+
1 row in set (0.00 sec)
irb(main):014:0> SkillAdjacency.where(adjacent_skill_id: 200, requested_skill: 1).explain
SkillAdjacency Load (0.3ms) SELECT `skill_adjacencies`.* FROM `skill_adjacencies` WHERE `skill_adjacencies`.`adjacent_skill_id` = 200 AND `skill_adjacencies`.`requested_skill_id` = 1
=> EXPLAIN for: SELECT `skill_adjacencies`.* FROM `skill_adjacencies` WHERE `skill_adjacencies`.`adjacent_skill_id` = 200 AND `skill_adjacencies`.`requested_skill_id` = 1
+----+-------------+-------------------+------------+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------+---------+-------------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------------------+------------+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------+---------+-------------+------+----------+-------+
| 1 | SIMPLE | skill_adjacencies | NULL | const | index_adjacencies_on_requested_then_adjacent,index_adjacencies_on_adjacent_then_requested,index_skill_adjacencies_on_requested_skill_id,index_skill_adjacencies_on_adjacent_skill_id | index_adjacencies_on_requested_then_adjacent | 10 | const,const | 1 | 100.0 | NULL |
+----+-------------+-------------------+------------+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------+---------+-------------+------+----------+-------+
1 row in set (0.00 sec)
В обоих случаях я вижу, что значение в * Столбец 1030 * равен index_adjacencies_on_requested_then_adjacent
, несмотря на то, что каждый запрос проходит в другом порядке для параметров запроса. Могу ли я предположить, что это означает, что порядок этих параметров не имеет значения?