考虑以下视图
CREATE VIEW `my_view` AS
SELECT
a.id,
(SELECT
COUNT( b.id )
FROM
another_table b
WHERE
b.a_id = a.id AND b.other_column = 'ABC'
) AS counter
FROM
some_table a
some_table
有数百万行,another_table
的索引位于a_id
+ other_column
。
现在,请考虑以下SQL:
SELECT vw.*
FROM some_table a
LEFT JOIN my_view vw on vw.id = a.id
WHERE a.id = 12345
有谁能告诉我为什么这个SQL查询正在some_table
上进行全表扫描?目标是使视图返回another_table
等于other_column
的{{1}}行数。
如果我用'ABC'
替换查询中的LEFT JOIN my_view
,它不会执行全表扫描并使用a_id + other_column索引。
我很难过。任何帮助表示赞赏。
答案 0 :(得分:1)
MySQL中的视图一般。 。 。 [我不想使用那个字]。 。 。表现不如人们所期望或想要的那么好。您认为:“哦,SQL引擎只会将视图定义插入到我的查询中,然后对其进行优化。”你并非完全错误。 MySQL做到了。它被称为视图的MERGE算法。
不幸的是,没有很多有用的视图可以使用MERGE算法。基本上,您可以使用它来重命名字段并在单个表上预先计算表达式。
替代算法是TEMPTABLE算法。如您所见,这会创建一个临时表,从而进行全表扫描。
当然,您可以在documentation中了解更多相关信息。
我不相信有任何简单的解决方法。您可以使用触发器创建摘要表并使其保持最新。但我并不认为这是“简单”。