mysql - 如何改进此查询 mysql 和 rails 5

标签 mysql ruby-on-rails performance mariadb

我们有三个表usersstoresstore_customer_associations,其中一个用户可以是许多商店.

我曾尝试在主键中放置另一个索引但没有成功(以及其他)。

(目前这些是我们在每个表中的索引)

mysql> SHOW INDEXES FROM store_customer_associations;
+-------+------------+-------------------------------------+--------------+----------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name                            | Seq_in_index | Column_name          | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+-------------------------------------+--------------+----------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| users |          0 | PRIMARY                             |            1 | id                   | A         |     9386515 |     NULL | NULL   |      | BTREE      |         |               |
| users |          0 | tmp_idx_users_id                    |            1 | id                   | A         |     9386515 |     NULL | NULL   |      | BTREE      |         |               |
+-------+------------+-------------------------------------+--------------+----------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
10 rows in set (0.00 sec)

mysql> SHOW INDEXES FROM store_customer_associations;
+-----------------------------+------------+-----------------------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table                       | Non_unique | Key_name                                      | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-----------------------------+------------+-----------------------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| store_customer_associations |          0 | PRIMARY                                       |            1 | id          | A         |    51298761 |     NULL | NULL   |      | BTREE      |         |               |
| store_customer_associations |          1 | index_store_customer_associations_on_store_id |            1 | store_id    | A         |       50096 |     NULL | NULL   | YES  | BTREE      |         |               |
| store_customer_associations |          1 | index_store_customer_associations_on_user_id  |            1 | user_id     | A         |    25649380 |     NULL | NULL   | YES  | BTREE      |         |               |
+-----------------------------+------------+-----------------------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
3 rows in set (0.00 sec)

我们使用的是 rails 5.1(这是一个大型的 rails 4 遗留数据库)。

然后我们需要使这个查询更快:

SELECT  COUNT(*)
    FROM  `users`
    INNER JOIN  `store_customer_associations`
         ON `users`.`id` = `store_customer_associations`.`user_id`
    WHERE  `store_customer_associations`.`store_id` = STORE_ID;

+----------+
| COUNT(*) |
+----------+
|  1997632 |
+----------+
1 row in set (6.64 sec)


mysql> EXPLAIN     SELECT  COUNT(*)
    FROM  `users`
    INNER JOIN  `store_customer_associations`
         ON `users`.`id` = `store_customer_associations`.`user_id`
    WHERE  `store_customer_associations`.`store_id` = STORE_ID;

+------+-------------+-----------------------------+--------+--------------------------------------------------------------------------------------------+-----------------------------------------------+---------+---------------------------------------------------------+---------+-------------+
| id   | select_type | table                       | type   | possible_keys                                                                              | key                                           | key_len | ref                             | rows    | Extra       |
+------+-------------+-----------------------------+--------+--------------------------------------------------------------------------------------------+-----------------------------------------------+---------+---------------------------------------------------------+---------+-------------+
|    1 | SIMPLE      | store_customer_associations | ref    | index_store_customer_associations_on_store_id,index_store_customer_associations_on_user_id | index_store_customer_associations_on_store_id | 5       | const                             | 4401812 | Using where |
|    1 | SIMPLE      | users                       | eq_ref | PRIMARY,tmp_idx_users_id                                                                   | PRIMARY                                       | 4       | trustvox_production.store_customer_associations.user_id |       1 | Using index |
+------+-------------+-----------------------------+--------+--------------------------------------------------------------------------------------------+-----------------------------------------------+---------+---------------------------------------------------------+---------+-------------+
2 rows in set (0.00 sec)

更新 1

mysql> EXPLAIN     SELECT  COUNT(*)
    FROM  `users`
    INNER JOIN  `store_customer_associations`
         ON `users`.`id` = `store_customer_associations`.`user_id`
    WHERE  `store_customer_associations`.`store_id` = STORE_ID;

+------+-------------+-----------------------------+--------+-------------------------------------------------------------------------------------------------------------+-----------------------------------------------+---------+---------------------------------------------------------+---------+-------------+
| id   | select_type | table                       | type   | possible_keys                                                                                               | key                                           | key_len | ref                                              | rows    | Extra       |
+------+-------------+-----------------------------+--------+-------------------------------------------------------------------------------------------------------------+-----------------------------------------------+---------+---------------------------------------------------------+---------+-------------+
|    1 | SIMPLE      | store_customer_associations | ref    | index_store_customer_associations_on_store_id,index_store_customer_associations_on_user_id,user_id_store_id | index_store_customer_associations_on_store_id | 5       | const                                              | 4401812 | Using where |
|    1 | SIMPLE      | users                       | eq_ref | PRIMARY,tmp_idx_users_id                                                                                    | PRIMARY                                       | 4       | trustvox_production.store_customer_associations.user_id |       1 | Using index |
+------+-------------+-----------------------------+--------+-------------------------------------------------------------------------------------------------------------+-----------------------------------------------+---------+---------------------------------------------------------+---------+-------------+
2 rows in set (0.00 sec)

更新 2

mysql>     SELECT  COUNT(*)
    FROM  users
    INNER JOIN  store_customer_associations
        FORCE INDEX FOR JOIN  (PRIMARY, user_id_store_id)
         ON users.id = store_customer_associations.user_id
    WHERE  store_customer_associations.store_id = STORE_ID;

+----------+
| COUNT(*) |
+----------+
|  1997632 |
+----------+
1 row in set (28.90 sec)

mysql> EXPLAIN     SELECT  COUNT(*)
    FROM  users
    INNER JOIN  store_customer_associations
        FORCE INDEX FOR JOIN  (PRIMARY, user_id_store_id)
         ON users.id = store_customer_associations.user_id
    WHERE  store_customer_associations.store_id = STORE_ID;
+------+-------------+-----------------------------+-------+--------------------------+------------------+---------+------------------------------------+---------+-------------+
| id   | select_type | table                       | type  | possible_keys            | key              | key_len | ref                                | rows    | Extra       |
+------+-------------+-----------------------------+-------+--------------------------+------------------+---------+------------------------------------+---------+-------------+
|    1 | SIMPLE      | users                       | index | PRIMARY,tmp_idx_users_id | tmp_idx_users_id | 4       | NULL                               | 8675689 | Using index |
|    1 | SIMPLE      | store_customer_associations | ref   | user_id_store_id         | user_id_store_id | 10      | trustvox_production.users.id,const |       1 | Using index |
+------+-------------+-----------------------------+-------+--------------------------+------------------+---------+------------------------------------+---------+-------------+
2 rows in set (0.00 sec)

mysql>

更新 3

mysql> EXPLAIN     SELECT  COUNT(*)
    FROM  users
    INNER JOIN  
        ( SELECT  *
            FROM  store_customer_associations
            WHERE  store_id = 75856
        ) sca  ON users.id = sca.user_id;

+------+-------------+-----------------------------+--------+-------------------------------------------------------------------------------------------------------------+-----------------------------------------------+---------+---------------------------------------------------------+---------+-------------+
| id   | select_type | table                       | type   | possible_keys                                                                                               | key                                           | key_len | ref                                              | rows    | Extra       |
+------+-------------+-----------------------------+--------+-------------------------------------------------------------------------------------------------------------+-----------------------------------------------+---------+---------------------------------------------------------+---------+-------------+
|    1 | SIMPLE      | store_customer_associations | ref    | index_store_customer_associations_on_store_id,index_store_customer_associations_on_user_id,user_id_store_id | index_store_customer_associations_on_store_id | 5       | const                                              | 4401812 | Using where |
|    1 | SIMPLE      | users                       | eq_ref | PRIMARY,tmp_idx_users_id                                                                                    | PRIMARY                                       | 4       | trustvox_production.store_customer_associations.user_id |       1 | Using index |
+------+-------------+-----------------------------+--------+-------------------------------------------------------------------------------------------------------------+-----------------------------------------------+---------+---------------------------------------------------------+---------+-------------+

更新 4

mysql> ALTER TABLE store_customer_associations DROP INDEX index_store_customer_associations_on_store_id;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> ALTER TABLE store_customer_associations DROP INDEX index_store_customer_associations_on_user_id;
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> CREATE INDEX index_on_store_id_and_user_id ON store_customer_associations (store_id, user_id);
Query OK, 0 rows affected (45.95 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> CREATE INDEX index_store_customer_associations_on_user_id ON store_customer_associations(user_id);
Query OK, 0 rows affected (33.06 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> CREATE INDEX index_store_customer_associations_on_store_id ON store_customer_associations(store_id);
Query OK, 0 rows affected (38.58 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> SHOW INDEXES FROM store_customer_associations;
+-----------------------------+------------+-----------------------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table                       | Non_unique | Key_name                                      | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-----------------------------+------------+-----------------------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| store_customer_associations |          0 | PRIMARY                                       |            1 | id          | A         |    10305620 |     NULL | NULL   |      | BTREE      |         |               |
| store_customer_associations |          1 | index_on_store_id_and_user_id                 |            1 | store_id    | A         |        8244 |     NULL | NULL   | YES  | BTREE      |         |               |
| store_customer_associations |          1 | index_on_store_id_and_user_id                 |            2 | user_id     | A         |    10305620 |     NULL | NULL   | YES  | BTREE      |         |               |
| store_customer_associations |          1 | index_store_customer_associations_on_user_id  |            1 | user_id     | A         |    10305620 |     NULL | NULL   | YES  | BTREE      |         |               |
| store_customer_associations |          1 | index_store_customer_associations_on_store_id |            1 | store_id    | A         |        6424 |     NULL | NULL   | YES  | BTREE      |         |               |
+-----------------------------+------------+-----------------------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
5 rows in set (0.00 sec)

最佳答案

store_customer_associations:  INDEX(store_id, user_id)  -- "covering"

store_id 是第一个——处理WHERE;添加了 user_id 以便触摸只需要索引。

让您自己发现 INDEX 的教程:http://mysql.rjweb.org/doc.php/index_cookbook_mysql

关于mysql - 如何改进此查询 mysql 和 rails 5,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49929996/

相关文章:

mysql - 通过 VBA 代码在 MS Access 中不区分大小写的过滤器

来自平面 MySQL 查询结果的 PHP 嵌套数组

ruby-on-rails - Rails 3.1.3 在使用 compass+sussy+haml+scss 编译 Assets 时在登台服务器中出错

excel - 在vba中寻找更有效的算法来评估指数增长的组合问题

c - 在未排序的数组中找到差值为输入值 'k' 的一对数字

mysql - 更改 MySQL 磁盘上的数据组织

MySQL 触发器以列的属性为目标

ruby-on-rails - 我在哪里放置 ActionMailer View 的辅助方法?

ruby-on-rails - (设计)更新时需要密码,即使它是空白的

performance - Apache Benchmark - 随机查询字符串?