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

为什么MySQL不使用我的索引?优化mysql选择查询,mysql,optimization,indexing,query-optimization,database-schema,Mysql,Optimization,Indexing,Query Optimization,Database Schema,我正在尝试优化MySQL select请求: 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

我正在尝试优化MySQL select请求:

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      |         |
+-------+------------+------------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
执行查询时,即使查询中没有国家/地区id,它也会在类型和国家/地区id上使用索引\u sales\u\u

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

但是,当我使用使用索引(查看了索引的销售额)时,它会下降到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在默认情况下不使用索引\u查看的销售额?有没有更好的指数


谢谢大家!

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

参考此

如果此列为空,则没有相关索引。在这种情况下,您可以通过检查WHERE子句来检查它是否引用了一些适合索引的列,从而提高查询的性能。如果是这样,请创建一个适当的索引并再次使用EXPLAIN检查查询


Mysql在类型和国家id上选择了索引,因为您不能与空值进行比较

发布查询的“解释”,这样我们就可以看到数据库的想法。