带有count()的MySQL视图执行全表扫描

时间:2014-11-10 19:29:47

标签: mysql sql-view full-table-scan

考虑以下视图

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索引。

我很难过。任何帮助表示赞赏。

1 个答案:

答案 0 :(得分:1)

MySQL中的视图一般。 。 。 [我不想使用那个字]。 。 。表现不如人们所期望或想要的那么好。您认为:“哦,SQL引擎只会将视图定义插入到我的查询中,然后对其进行优化。”你并非完全错误。 MySQL做到了。它被称为视图的MERGE算法。

不幸的是,没有很多有用的视图可以使用MERGE算法。基本上,您可以使用它来重命名字段并在单个表上预先计算表达式。

替代算法是TEMPTABLE算法。如您所见,这会创建一个临时表,从而进行全表扫描。

当然,您可以在documentation中了解更多相关信息。

我不相信有任何简单的解决方法。您可以使用触发器创建摘要表并使其保持最新。但我并不认为这是“简单”。