我有一些类似的联接集合的查询。由于某些原因,他们都遭受了其中一个连接的表扫描。
SELECT S.shape_id,
S.title,
G.grid_id,
CI.city_id,
CI.city_name,
CO.country_code,
CO.country,
U.user_id,
U.username,
GA.first_name,
GA.fb_id
FROM shape S
JOIN spots SP ON S.shape_id = SP.shape_id
JOIN grid G ON SP.grid_id = G.grid_id
JOIN city CI on G.city_id = CI.city_id
JOIN country CO ON CI.country_code = CO.country_code
JOIN user U on S.user_id = U.user_id
LEFT JOIN gamer GA ON U.user_id = GA.user_id
WHERE S.status > 0
AND U.user_id != 2579
ORDER BY S.views ASC
LIMIT 111, 1
表扫描似乎总是在'grid'/'G'表上。
这是'EXPLAIN'
ID - SELECT TYPE - TABLE - TYPE - POSS KEYS - KEY - KEY LEN - REF - ROWS - EXTRA ----------------------------------------------------------------------------------- 1 - SIMPLE - G - ALL - PRIMARY - null - null - null - 405 - Using temporary; Using filesort 1 - SIMPLE - CI - eq_ref - PRIMARY - PRIMARY - 3 - ft_game.G.city_id - 1 1 - SIMPLE - CO - eq_ref - PRIMARY - PRIMARY - 6 - ft_game.CI.country_code - 1 1 - SIMPLE - SP - ref - shape_id,grid_id - grid_id - 4 - ft_game.G.grid_id - 1 - Using where 1 - SIMPLE - S - eq_ref - PRIMARY,user_id - PRIMARY - 4 - ft_game.SP.shape_id - 1 - Using where 1 - SIMPLE - U - eq_ref - PRIMARY - PRIMARY - 3 - ft_game.S.user_id - 1 1 - SIMPLE - GA - eq_ref - PRIMARY - PRIMARY - 3 - ft_game.S.user_id - 1
答案 0 :(得分:0)
我不是mysql的大师。另一方面,我认为Oracle的基线是相似的。基于它们:
全表扫描或索引扫描背后的主要驱动因素是选择性。列中存在的值越多,使用索引的可能性就越大。如果数据库预计将获取超过10%的行,则可能会使用全表扫描。
我认为gridId在网格表中是唯一的。所以选择性很高。但是你使用其他列city_id。这意味着,即使您使用索引来获取id,也需要表数据,因为附加列就在那里。如果这意味着,将提取超过10%的行,则不会使用索引。
有多种连接方法。基于join method,存在不同的行为。
对于hash join和nested loops,驱动程序表是较小或最小的,或具有最具选择性谓词的驱动程序表。所以我认为网格是你最小的桌子。由于你的SQL没有任何基于等价的条件(你有一个>和一个!=),你不应该怀疑该数据库是否会使用最小的表作为驱动程序。
因此,全表扫描的主要原因是您没有任何选择条件,数据库应从全表扫描开始,并选择网格。多数民众赞成。
答案 1 :(得分:0)
你说这张桌子只有400行。我知道在SQL Server中,不太可能在这样的小表中使用索引。我怀疑mySQL会有同样的感觉。
如果表很大并且仍未使用索引,请检查以确保您具有良好的索引以供其使用。例如,FK通常应该被索引,有些人认为它们是自动的,但它们并不在所有数据库中。你会惊讶地发现你的第一张支票经常没有显示你确定会有的指数。