我的查询目前大约需要3秒钟,我相信我可以对其进行优化。我只是想不出如何优化它。
我的应用程序有一个相当大的products
表(大约500,000条记录)。每个产品都可以列在50个域之一(列在domains
表中)。产品和域之间的链接存储在domains_products
表(大约有1,400,000条记录)中。慢查询在我的应用程序的管理部分中,我需要能够查看未在任何域中列出的产品。
删除了所有不相关联接的裸骨,有问题的查询是:
SELECT `products`.*
FROM `products`
LEFT JOIN `domains_products`
ON `domains_products`.`product_id` = `products`.`id`
WHERE `products`.`deleted` = 'N'
AND `domains_products`.`domain_id` IS NULL
ORDER BY `products`.`id` ASC
在此表单中,查询需要3秒以上的时间并返回3,000多个产品(这是正确的)。如果我删除WHERE
子句,则查询需要0.12秒(但显然不会返回正确的结果)。
两个表都使用InnoDB引擎。 products
表在id
列上有一个主键,在deleted
列上有一个索引。 domains_products
表只有product_id
和domain_id
列,主键位于这两列上,并且它们都有自己的索引。所有相关列均为NOT NULL
列。
EXPLAIN
给了我这个:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE products ref deleted deleted 1 const 188616 Using where
1 SIMPLE domains_products ref product_id product_id 4 products.id 1 Using where; Using index; Not exists
请注意,虽然MySQL发现了正确的密钥,但它实际上似乎并没有使用它们。
剖析器说:
Status Time
Starting 62 µs
Checking Permissions 7 µs
Checking Permissions 5 µs
Opening Tables 38 µs
System Lock 13 µs
Init 37 µs
Optimizing 17 µs
Statistics 1,3 ms
Preparing 25 µs
Executing 5 µs
Sorting Result 5 µs
Sending Data 3,3 s
End 28 µs
Query End 8 µs
Closing Tables 25 µs
Freeing Items 297 µs
Logging Slow Query 4 µs
Cleaning Up 5 µs
请注意,它似乎挂在Sending Data
上。我试过用NOT IN替换连接:
SELECT `products`.*
FROM `products`
WHERE `products`.`deleted` = 'N'
AND `product`.`id` NOT IN (
SELECT `product_id`
FROM `domains_products`
)
ORDER BY `products`.`id` ASC
此查询提供完全相同的结果,但需要3.8秒。
有人能指出我正确的方向来优化此查询吗?
答案 0 :(得分:1)
似乎问题出在“已删除”列中。我猜测产品表中的几乎所有项目都标有“N”,这使得“已删除”列中的索引在这种情况下毫无用处。
你可以做的一件事就是创建另一个表,比如说存储了product_id的deleted_domains_products(以及你想要的domain_id)。然后创建一个触发器,这样每次从domains_products中删除一个条目时,它都会在该表中插入一个条目。那么你将有一个较小的集合来查询。当你完成后,你可以在下次截断该表,所以它总是很快。
答案 1 :(得分:0)
尝试创建以下索引,然后重新运行查询:
告诉我们这是怎么回事
答案 2 :(得分:0)
试试这个,让我知道它的时间。
SELECT `products`.*
FROM `products`
WHERE `products`.`deleted` = 'N'
AND NOT EXISTS (SELECT 1
FROM `domains_products`
WHERE `domains_products`.`product_id` = `products`.`id`
);
ORDER BY `products`.`id` ASC