【发布时间】:2021-11-06 19:57:22
【问题描述】:
我将首先显示我的查询,然后是表格。我试过强制索引,但它不会。当查询的该部分作为新查询单独运行时,它使用索引并且速度很快,但由于它不会出现在我的完整查询中,因此速度非常慢/永远不会完成。
SELECT p.*, INET_NTOA(p.ip) AS ipStr, qs.score, db.*
FROM proxies p
LEFT JOIN ipdb db FORCE INDEX FOR JOIN (`iprange`)
ON db.ipStart <= p.ip AND db.ipEnd >= p.ip
LEFT JOIN ipqs qs ON qs.ip = p.ip
WHERE expiration_date < '2021-09-18'
ORDER BY expiration_date
LIMIT 500
'iprange' 是 ipStart + ipEnd 上的索引。 p.ip和expiration_date上有索引
解释结果:
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
|---|---|---|---|---|---|---|---|---|---|
| 1 | SIMPLE | p | range | expirationdate | expirationdate | 4 | NULL | 2547 | Using index condition |
| 1 | SIMPLE | db | ALL | iprange | NULL | NULL | NULL | 8334413 | Range checked for each record (index map: 0x2) |
| 1 | SIMPLE | qs | eq_ref | PRIMARY | PRIMARY | 4 | adscend_Aff.p.ip | 1 | NULL |
ipdb的查询,自己跑,有时用索引有时不用....不用时17秒,用时0.4秒。
explain SELECT * FROM ipdb db WHERE db.ipStart <= 785476891 AND db.ipEnd >= 785476891;
explain SELECT * from ipdb db where db.ipStart <= 16941057 AND db.ipEnd >= 16941057;
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
|---|---|---|---|---|---|---|---|---|---|
| 1 | SIMPLE | db | ALL | iprange | NULL | NULL | NULL | 8334413 | Using where |
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
|---|---|---|---|---|---|---|---|---|---|
| 1 | SIMPLE | db | range | iprange | iprange | 4 | NULL | 86 | Using index condition |
当我强制索引时:
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
|---|---|---|---|---|---|---|---|---|---|
| 1 | SIMPLE | db | range | iprange | iprange | 4 | NULL | 1818402 | Using index condition |
需要 1.8 秒。
在较大的查询中尝试使用 FORCE INDEX 而不是 FORCE INDEX FOR JOIN,但没有区别。不知道如何解决这个问题。尝试将其分为两步并在 php 循环中执行第二步,但这样仍然非常慢
【问题讨论】:
-
请提供
SHOW CREATE TABLE。表中大约有多少行?以及每个样本中有多少SELECT。 (这些值是“为什么”的线索。)
标签: mysql join left-join query-optimization