为什么 Left outer Join 没有正确使用索引
Why does Left outer Join not use the index correctly
我有两个 table 分别称为配置文件和详细信息。详细信息 table 在城市列中有索引。这是我的查询:
select *
from profiles p
left outer join details d
use index(details_city)
on (p.id = d.pid)
where (d.city = ‘york’ or p.city = 'york')
order by p.id
当我对其进行解释时,我可以看到 city 列上 details table 的索引甚至没有被使用。
在MySQL中有没有限制在这种情况下不使用索引。
我怀疑您会在内部联接中看到相同的行为。在此语句中,WHERE 子句中的谓词否定 LEFT JOIN 的 "outerness"。我认为它与 LEFT JOIN 没有任何关系。
WHERE 子句中的谓词...city LIKE '%...'
、MySQL 不能使用索引范围扫描操作。它必须为 table 中的每一行(或未被过滤掉的每一行)评估 city
的值。
此外,您要从 details
table 返回 每个 列,并且 MySQL 不能满足仅使用索引,它将不得不访问底层 table 中的页面以获取这些列的值。
MySQL 正在判断不同的访问计划比使用带有城市前导列的索引具有更低的成本。在连接谓词 = d.pid
中有一个相等比较。 MySQL 可以使用具有前导列的索引来满足这一点。
最有可能对此查询有益的索引是复合索引:
... ON details (pid, city)
OR
破坏了所有优化尝试。这应该工作得更快,特别是如果表很大:
SELECT p.*, d.*
FROM (
-- Get what you can from `profiles`:
( SELECT id
FROM profiles
WHERE city = 'york'
)
UNION DISTINCT
-- Get what you can by starting from `details`:
( SELECT p.id
FROM profiles p
JOIN details d ON (p.id = d.pid)
WHERE d.city = 'york' )
) AS u
JOIN profiles p ON p.id = u.id
LEFT JOIN details d ON d.pid = p.id
ORDER BY p.id
每个内部 SELECT
将使用不同的索引,因此可以进行优化。您将需要这些索引:
d: INDEX(city, pid), INDEX(pid)
p: PRIMARY KEY(id), INDEX(city, id)
而且您不需要任何形式的 USE INDEX
。
(不要使用有趣的撇号:‘york’
。)
(OUTER
是可选的,没有影响。)
(如果您需要 city LIKE '%york%', consider
FULLTEXT`。)
为什么,请告诉我,你在两个表中都有 city
?!?修复可能会导致 真正的 解决方案。
我有两个 table 分别称为配置文件和详细信息。详细信息 table 在城市列中有索引。这是我的查询:
select *
from profiles p
left outer join details d
use index(details_city)
on (p.id = d.pid)
where (d.city = ‘york’ or p.city = 'york')
order by p.id
当我对其进行解释时,我可以看到 city 列上 details table 的索引甚至没有被使用。
在MySQL中有没有限制在这种情况下不使用索引。
我怀疑您会在内部联接中看到相同的行为。在此语句中,WHERE 子句中的谓词否定 LEFT JOIN 的 "outerness"。我认为它与 LEFT JOIN 没有任何关系。
WHERE 子句中的谓词...city LIKE '%...'
、MySQL 不能使用索引范围扫描操作。它必须为 table 中的每一行(或未被过滤掉的每一行)评估 city
的值。
此外,您要从 details
table 返回 每个 列,并且 MySQL 不能满足仅使用索引,它将不得不访问底层 table 中的页面以获取这些列的值。
MySQL 正在判断不同的访问计划比使用带有城市前导列的索引具有更低的成本。在连接谓词 = d.pid
中有一个相等比较。 MySQL 可以使用具有前导列的索引来满足这一点。
最有可能对此查询有益的索引是复合索引:
... ON details (pid, city)
OR
破坏了所有优化尝试。这应该工作得更快,特别是如果表很大:
SELECT p.*, d.*
FROM (
-- Get what you can from `profiles`:
( SELECT id
FROM profiles
WHERE city = 'york'
)
UNION DISTINCT
-- Get what you can by starting from `details`:
( SELECT p.id
FROM profiles p
JOIN details d ON (p.id = d.pid)
WHERE d.city = 'york' )
) AS u
JOIN profiles p ON p.id = u.id
LEFT JOIN details d ON d.pid = p.id
ORDER BY p.id
每个内部 SELECT
将使用不同的索引,因此可以进行优化。您将需要这些索引:
d: INDEX(city, pid), INDEX(pid)
p: PRIMARY KEY(id), INDEX(city, id)
而且您不需要任何形式的 USE INDEX
。
(不要使用有趣的撇号:‘york’
。)
(OUTER
是可选的,没有影响。)
(如果您需要 city LIKE '%york%', consider
FULLTEXT`。)
为什么,请告诉我,你在两个表中都有 city
?!?修复可能会导致 真正的 解决方案。