В случае составного индекса, какой порядок столбцов используют запросы ActiveRecord для определения составного индекса для поиска? - PullRequest
3 голосов
/ 09 июля 2020
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, несмотря на то, что каждый запрос проходит в другом порядке для параметров запроса. Могу ли я предположить, что это означает, что порядок этих параметров не имеет значения?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...