我有两张表,main_part
(3k记录)和part_details
(25k记录)
我尝试了以下索引,但explain
始终返回25k记录的全表扫描,而不是大约2k匹配记录和Using where; Using temporary; Using filesort
ALTER TABLE `main_part` ADD INDEX `main_part_index_1` (`unit`);
ALTER TABLE `part_details` ADD INDEX `part_details_index_1` (`approved`, `display`, `country`, `id`, `price`);
这是我的问题:
SELECT a.part_id, b.my_title,
b.price, a.type,
a.unit, a.certification,
b.my_image,
b.price/a.unit AS priceW
FROM main_part AS a
INNER JOIN part_details AS b ON a.part_id=b.id
WHERE b.approved = 'Yes'
AND b.display = 'On'
AND b.country = 'US'
AND a.unit >= 300
ORDER BY b.price ASC LIMIT 50
我知道的一件事是a.part_id不是main_part表中的主键。这可能是罪魁祸首吗?
创建表SQL:
CREATE TABLE `main_part` (
`id` smallint(6) NOT NULL AUTO_INCREMENT,
`part_id` mediumint(9) NOT NULL DEFAULT '0',
`type` varchar(50) NOT NULL DEFAULT '',
`unit` varchar(50) NOT NULL DEFAULT '',
`certification` varchar(50) NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `part_details` (
`id` mediumint(9) NOT NULL AUTO_INCREMENT,
`asn` varchar(50) NOT NULL DEFAULT '',
`country` varchar(5) NOT NULL DEFAULT '',
`my_title` varchar(200) NOT NULL DEFAULT '',
`display` varchar(5) NOT NULL DEFAULT 'On',
`approved` varchar(5) NOT NULL DEFAULT 'No',
`price` decimal(7,3) NOT NULL DEFAULT '0.000',
`my_image` varchar(250) NOT NULL DEFAULT '',
`update_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `countryasn` (`country`,`asn`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
答案 0 :(得分:3)
对于您的查询,更重要的索引是JOIN
条件,因为您已经知道a.part_id
不是主键,所以没有默认索引和您的第一个尝试应该是:
ALTER TABLE `main_part` ADD INDEX `main_part_index_1` (`part_id`,`unit`);
因为我们首先对JOIN
条件感兴趣,所以您还应该将第二个索引更改为
ALTER TABLE `part_details` ADD INDEX `part_details_index_1`
(`id`, `approved`, `display`, `country`, `price`);
订单在索引
中很重要另一个提示是从基本查询开始:
SELECT *
FROM main_part AS a
INNER JOIN part_details AS b ON a.part_id=b.id
为part_id
和id
添加索引,检查解释计划,然后开始添加条件并在需要时更新索引。
答案 1 :(得分:1)
似乎用于过滤part_details的大多数列都没有选择性(显示可能是一个开/关开关,国家在许多产品中可能非常相似,等等。)
在某些情况下,当WHERE子句选择性不高时,MySQL可能会选择使用更适合ORDER BY子句的索引。
我也会尝试创建此索引并检查解释计划是否有任何更改:
ALTER TABLE `part_details` ADD INDEX `part_details_price_index` (`price`);
答案 2 :(得分:0)
对于此查询:
SELECT mp.part_id, pd.my_title, pd.price, mp.type,
mp.unit, mp.certification, pd.my_image,
pd.price/mp.unit AS priceW
FROM main_part mp INNER JOIN
part_details pd
ON mp.part_id = pd.id
WHERE pd.approved = 'Yes' AND
pd.display = 'On' AND
pd.country = 'US' AND
mp.unit >= 300
ORDER BY pd.price ASC
LIMIT 50;
对于此查询,我将从part_details(country, display, approved, id, price)
和main_part(part_id, unit)
上的索引开始。
part_details
上的索引可用于join
之前的过滤。要摆脱order by
的排序并不容易。