我的查询目前大约需要 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 秒。
谁能指出我优化此查询的正确方向?