mysql - 为什么 MySQL 不使用我的索引?优化mysql select查询

标签 mysql optimization indexing query-optimization database-schema

我正在尝试优化 MySQL 选择请求:

SELECT * FROM `sales` 
WHERE ((sales.private = false AND (sales.buyer_id IS NULL OR NOT sales.buyer_id=142)
  AND (sales.merchand_id IS NULL OR NOT sales.merchand_id=142)
  AND (sales.private_item = false) )
  AND ((sales.buyer_id=32 OR sales.merchand_id=32)
  AND (sales.admin=0 AND NOT sales.type IN ('book'))))
ORDER BY sales.created_at DESC, sales.id DESC LIMIT 0, 10;

表的架构是

mysql> SHOW columns from sales;
+------------------------+--------------+------+-----+---------+----------------+
| Field                  | Type         | Null | Key | Default | Extra          |
+------------------------+--------------+------+-----+---------+----------------+
| id                     | int(11)      | NO   | PRI | NULL    | auto_increment |
| type                   | varchar(255) | YES  | MUL | NULL    |                |
| buyer_id               | int(11)      | YES  | MUL | NULL    |                |
| merchand_id            | int(11)      | YES  | MUL | NULL    |                |
| private                | tinyint(1)   | YES  |     | 0       |                |
| admin                  | tinyint(1)   | YES  |     | 0       |                |
| created_at             | datetime     | YES  |     | NULL    |                |
| updated_at             | datetime     | YES  |     | NULL    |                |
| country_id             | int(11)      | YES  | MUL | 0       |                |
| private_item           | tinyint(1)   | YES  |     | 0       |                |
+------------------------+--------------+------+-----+---------+----------------+

索引是:

    mysql> show indexes from sales;
+-----------------+------------+--------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name                           | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-----------------+------------+--------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| sales |          0 | PRIMARY                            |            1 | id          | A         |      286509 |     NULL | NULL   |      | BTREE      |         |
| sales |          1 | index_sales_on_type                |            1 | type        | A         |         123 |     NULL | NULL   | YES  | BTREE      |         |
| sales |          1 | index_sales_on_buyer_id            |            1 | buyer_id    | A         |       40929 |     NULL | NULL   | YES  | BTREE      |         |
| sales |          1 | index_sales_on_merchand_id         |            1 | merchand_id | A         |       40929 |     NULL | NULL   | YES  | BTREE      |         |
| sales |          1 | index_sales_on_country_id          |            1 | country_id  | A         |           6 |     NULL | NULL   | YES  | BTREE      |         |
| sales |          1 | index_sales_on_type_and_country_id |            1 | type        | A         |         151 |     NULL | NULL   | YES  | BTREE      |         |
| sales |          1 | index_sales_on_type_and_country_id |            2 | country_id  | A         |         428 |     NULL | NULL   | YES  | BTREE      |         |
| sales |          1 | index_sales_viewed                 |            1 | buyer_id    | A         |       35813 |     NULL | NULL   | YES  | BTREE      |         |
| sales |          1 | index_sales_viewed                 |            2 | merchand_id | A         |      286509 |     NULL | NULL   | YES  | BTREE      |         |
| sales |          1 | index_sales_viewed                 |            3 | private_item| A         |      285009 |     NULL | NULL   | YES  | BTREE      |         |
| sales |          1 | index_sales_viewed                 |            4 | admin       | A         |      285009 |     NULL | NULL   | YES  | BTREE      |         |
| sales |          1 | index_sales_viewed                 |            5 | type        | A         |      285009 |     NULL | NULL   | YES  | BTREE      |         |
| sales |          1 | index_sales_viewed                 |            6 | private     | A         |      285009 |     NULL | NULL   | YES  | BTREE      |         |
| sales |          1 | index_sales_viewed                 |            7 | created_at  | A         |      285009 |     NULL | NULL   | YES  | BTREE      |         |
+-------+------------+------------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+

执行查询时,即使查询中没有country_id,它也会使用index_sales_on_type_and_country_id...

使用此索引进行查询需要 2.5 秒。

但是当我使用 USE INDEX(index_sales_viewed) 时,它会下降到 0.2 秒。

这是查询的解释:

+----+-------------+-----------------+------+----------------------------------------------+------+---------+------+--------+---------------------
| id | select_type | table | type  | possible_keys  | key                                | key_len | ref  | rows   | Extra                       | 
+----+-------------+-----------------+------+----------------------------------------------+------+---------+------+--------+---------------------
|  1 | SIMPLE      | sales | range |  see bellow    | index_sales_on_type_and_country_id | 258     | NULL | 208725 | Using where; Using filesort | 
+----+-------------+-----------------+------+----------------------------------------------+------+---------+------+--------+---------------------

可能的键是:

index_sales_on_type,
index_sales_on_buyer_id,
index_sales_on_merchand_id,
index_sales_on_type_and_country_id,
index_sales_public_recent_activity

为什么 MySQL 默认不使用 index_sales_viewed?还有更好的索引吗?

谢谢!

最佳答案

这是对 NULL 的错误使用,请将索引中使用的所有列更改为 NOT NULL

引用这个When to use NULL in MySQL tables

official documentation

If this column is NULL, there are no relevant indexes. In this case, you may be able to improve the performance of your query by examining the WHERE clause to check whether it refers to some column or columns that would be suitable for indexing. If so, create an appropriate index and check the query with EXPLAIN again

Mysql选择索引index_sales_on_type_and_country_id,因为你不与NULL值进行比较

关于mysql - 为什么 MySQL 不使用我的索引?优化mysql select查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7287295/

相关文章:

eclipse - 有没有自动优化Eclipse.ini文件的插件?

mysql - 优化查询以不使用文件排序

python - 读取 Dataframe 中的 2 个单元格值

含有非法字符的 MySQL 数据库名称

python - Python 中最快的图像迭代

java - Zookeeper/Chubby -vs- MySql NDB

sql - AS/400 DB2逻辑文件与表索引

python - 删除 Pandas 中索引未唯一标识的行

php mysql select 下拉选择和不同的查询

Mysql - 更新+插入json