结合UNION ALL的表的VIEW的MySQL性能

尤里(Yuriy Nakonechnyy)

假设我在MySQL中有2个表

create table `persons` (
    `id` bigint unsigned not null auto_increment,

    `first_name` varchar(64),
    `surname` varchar(64),

    primary key(`id`)
);

create table `companies` (
    `id` bigint unsigned not null auto_increment,

    `name` varchar(128),

    primary key(`id`)
);

现在,我经常需要对它们进行相同的处理,这就是以下查询的原因:

select person.id as `id`, concat(person.first_name, ' ', person.surname) as `name`, 'person' as `person_type`
from persons
union all
select company.id as `id`, company.name as `name`, 'company' as `person_type`
from companies

开始经常出现在其他查询中:作为联接或子选择的一部分现在,我只是将查询插入到联接或子选择中,例如:

select *
from some_table row
     left outer join (>>> query from above goes here <<<) as `persons`
     on row.person_id = persons.id and row.person_type = persons.person_type

但是,今天,我不得不多次使用讨论过的联合查询到另一个查询中,即两次将其联接。

因为我从未有过的体验意见,并听取了他们有很多缺点,我的问题是:

为讨论的联合查询创建视图并将其用于我的联接,子选择这是正常的做法吗?在性能方面-与仅将其插入联接,子选择相比,会更糟,是否相等或更好在这种情况下,有视图有任何弊端吗?

在此先感谢您的帮助!

spencer7593

我同意Bill Karwin的出色回答中的所有观点。

问:为讨论的联合查询创建视图并在我的联接,子选择等中使用它是正常的做法吗?

答:对于MySQL,更常见的做法是避免使用“ CREATE VIEW”语句。

问:就性能而言-与仅将其插入联接,子选择等相比,会更糟,是否相等或更好?

答:引用视图对象将具有与等效的嵌入式视图相同的性能。

(查找视图对象,检查特权,然后用存储的SQL替换视图引用可能要花更多的时间,而发送的语句要长得多。差异微不足道。)

问:在这种情况下拥有视图是否有任何弊端?

答:最大的缺点是MySQL如何处理视图(无论是存储视图还是内联视图)。MySQL将始终运行视图查询并将该查询的结果具体化为临时MyISAM表。但是无论是存储视图定义还是内联视图都没有区别。(其他RDBMS处理视图的方式与MySQL截然不同)。

视图的一个大缺点是,来自外部查询的谓词永远不会被下推到视图查询中。每次引用该视图时,即使使用单个id值查询,MySQL都将运行该视图查询并创建一个临时MyISAM表(上面没有索引),然后MySQL将对该临时表运行外部查询MyISAM表。

因此,就性能而言,请考虑对与“ CREATE TEMPORARY TABLE t (cols) ENGINE=MyISAM”和“ INSERT INTO t (cols) SELECT ...相提并论的观点的引用

MySQL实际上将内联视图称为“派生表”,当我们了解MySQL在做什么时,该名称很有意义。


我个人的喜好是不要使用“ CREATE VIEW”语句。最大的缺点(如我所见)是它“隐藏”正在执行的SQL。对于将来的读者来说,对该视图的引用就像一张表。然后,当他去编写SQL语句时,他将像表一样引用视图,因此非常方便。然后,他决定要将该表与自身连接,并对其进行另一个引用。(作为第二个参考,MySQL还再次运行该查询,并创建了另一个临时(且未建立索引)MyISAM表。现在,在该表上进行了JOIN操作。然后添加了谓词“ WHERE view.column ='foo'”在外部查询。

最终,它“隐藏”了最明显的性能改进,使谓词滑入视图查询。

然后,有人来决定他们要创建引用旧视图的新视图。他只需要一部分行,并且不能修改现有视图,因为这可能会破坏某些内容,因此他创建了一个新视图...从publicview创建视图myview p在哪里p.col ='foo'。

而且,现在,对myview的引用将首先运行publicview查询,创建一个临时MyISAM表,然后针对该myview查询运行,创建另一个临时MyISAM表,外部查询将针对该表运行。

基本上,视图的便利性可能会导致意外的性能问题。数据库中有可用的视图定义供任何人使用,即使不是最合适的解决方案,也将有人使用。

至少在内联视图中,编写SQL语句的人更了解实际正在执行的SQL,并且将所有SQL布局都可以对其进行性能调整。

我的两分钱。

驯服SQL

我发现应用常规的格式设置规则(我的工具会自动执行该规则)会使大量SQL变成我可以阅读和使用的东西。

SELECT row.col1
     , row.col2
     , person.*
  FROM some_table row
  LEFT
  JOIN ( SELECT 'person'  AS `person_type`
              , p.id      AS `id`
              , CONCAT(p.first_name,' ',p.surname) AS `name`
           FROM person p
          UNION ALL
         SELECT 'company' AS `person_type`
              , c.id      AS `id`
              , c.name    AS `name`
           FROM company c
       ) person
    ON person.id = row.person_id
   AND person.person_type = row.person_type

我同样有可能完全避免使用内联视图,并在SELECT列表中使用条件表达式,尽管对于许多列而言,这样做确实更加麻烦。

SELECT row.col1
     , row.col2
     , row.person_type AS ref_person_type
     , row.person_id   AS ref_person_id
     , CASE
       WHEN row.person_type = 'person'  THEN p.id 
       WHEN row.person_type = 'company' THEN c.id
       END AS `person_id`
     , CASE
       WHEN row.person_type = 'person'  THEN CONCAT(p.first_name,' ',p.surname)
       WHEN row.person_type = 'company' THEN c.name
       END AS `name`
  FROM some_table row
  LEFT
  JOIN person p
    ON row.person_type = 'person'
   AND p.id = row.person_id
  LEFT
  JOIN company c
    ON row.person_type = 'company'
   AND c.id = row.person_id

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

结合MySQL表与查询UNION或JOIN?

来自分类Dev

SQL子查询与UNION ALL查询结合

来自分类Dev

如何将select *与union结合使用?MySQL的

来自分类Dev

MySQL中UNION ALL的性能不佳

来自分类Dev

结合where子句的MySQL性能

来自分类Dev

大表的UNION的性能问题

来自分类Dev

性能:结合大数据表

来自分类Dev

性能:结合大数据表

来自分类Dev

结合唯一键的MySQL性能

来自分类Dev

在两个联合的(UNION ALL)大型表中提高SELECT性能

来自分类Dev

带有 Union All 的 View 中的 MySQL Case 语句

来自分类Dev

MySQL结合表查询数据

来自分类Dev

MySQL结合表查询数据

来自分类Dev

php mysql UNION ALL - 从单独的表中获取 id

来自分类Dev

MySQL UNION ALL与LEFT JOIN

来自分类Dev

MySQL搜索,结合表和元数据

来自分类Dev

使用 UNION 的性能问题

来自分类Dev

Presto上的UNION ALL / UNION

来自分类Dev

使用UNION ALL添加任意元组时的性能损失

来自分类Dev

Teradata /将记录与UNION结合使用不起作用

来自分类Dev

结合UNION和EXCEPT语句时,sqlite中的括号

来自分类Dev

将 LIMIT 与 UNION 结合使用时 MariaDB 的奇怪行为

来自分类Dev

将两个 CTE 与 UNION 结合会导致错误

来自分类Dev

结合mysql结果

来自分类Dev

MySQL结合外部联接

来自分类Dev

UNION ALL查询不匹配的表

来自分类Dev

UNION ALL,半总计数,不同的表

来自分类Dev

使用UNION / UNION ALL和Group By的MySQL查询错误

来自分类Dev

如何用union联接表?MySQL的