我的查询目前大约需要3秒,我敢肯定可以优化。我无法弄清楚如何优化它。需要帮助优化MySQL查询与“不在”加入
我的应用程序有一个合理的大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秒,超过3000种产品将返回一点(这是正确的)。如果我删除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秒。
任何人都可以指向正确的方向来优化此查询吗?
Re:“请注意,虽然MySQL已经发现了正确的密钥,但实际上并没有使用它们”:你说的是什么? – ruakh
您是否删除了大部分表格或进行了其他大型编辑?也许一个['OPTIMIZE TABLE'](http://dev.mysql.com/doc/refman/5.1/en/optimize-table.html)可以解决这个问题。 –
@ruakh我不是阅读EXPLAIN语法的专家,但是因为它在Extra-column中说“使用where”,所以我假设MySQL没有使用索引。如我错了请纠正我。 – rickdenhaan