我正在尝试优化 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
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/