草庐IT

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

coder 2023-10-09 原文

假设我在和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

开始经常出现在其他查询中:作为的一部分,加入子选择
现在,我只是简单地将此查询注入(inject)联接子选择中,例如:
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

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

由于我从没有过使用的经验,并且听说它们有很多缺点,所以我的问题是:

在讨论的联合查询中创建 View 并在我的中加入子选择等,这是正常的做法吗?就性能而言-与仅将其插入加入子选择等相比,会更差,相等还是更好?在这种情况下,使用 View 有什么缺点吗?

在此先感谢您的帮助!

最佳答案

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

问:是否正常创建用于讨论的联合查询的 View 并将其用于我的联接,子选择等中?

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

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

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

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

问:在这种情况下,有 View 有任何缺点吗?

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

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

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

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

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

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

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

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

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

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

我的两分钱。

TAMING BEASTLY 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

我同样有可能完全避免使用内联 View ,并在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

关于结合UNION ALL的表的VIEW的MySQL性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22544181/

有关结合UNION ALL的表的VIEW的MySQL性能的更多相关文章

  1. ruby-on-rails - 结合 meta_search 与 acts_as_taggable_on - 2

    我在开发的Rails3网站的一些搜索功能上遇到了一个小问题。我有一个简单的Post模型,如下所示:classPost我正在使用acts_as_taggable_on来更轻松地向我的帖子添加标签。当我有一个标记为“rails”的帖子并执行以下操作时,一切正常:@posts=Post.tagged_with("rails")问题是,我还想搜索帖子的标题。当我有一篇标题为“Helloworld”并标记为“rails”的帖子时,我希望能够通过搜索“hello”或“rails”来找到这篇帖子。因此,我希望标题列的LIKE语句与acts_as_taggable_on提供的tagged_with方法

  2. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  3. ruby-on-rails - 渲染另一个 Controller 的 View - 2

    我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>

  4. ruby-on-rails - 如何在我的 Rails 应用程序 View 中打印 ruby​​ 变量的内容? - 2

    我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby​​中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R

  5. ruby-on-rails - 如何在 Rails View 上显示错误消息? - 2

    我是rails的新手,想在form字段上应用验证。myviewsnew.html.erb.....模拟.rbclassSimulation{:in=>1..25,:message=>'Therowmustbebetween1and25'}end模拟Controller.rbclassSimulationsController我想检查模型类中row字段的整数范围,如果不在范围内则返回错误信息。我可以检查上面代码的范围,但无法返回错误消息提前致谢 最佳答案 关键是您使用的是模型表单,一种显示ActiveRecord模型实例属性的表单。c

  6. ruby-on-rails - 复数 for fields_for has_many 关联未显示在 View 中 - 2

    目前,Itembelongs_toCompany和has_manyItemVariants。我正在尝试使用嵌套的fields_for通过Item表单添加ItemVariant字段,但是使用:item_variants不显示该表单。只有当我使用单数时才会显示。我检查了我的关联,它们似乎是正确的,这可能与嵌套在公司下的项目有关,还是我遗漏了其他东西?提前致谢。注意:下面的代码片段中省略了不相关的代码。编辑:不知道这是否相关,但我正在使用CanCan进行身份验证。routes.rbresources:companiesdoresources:itemsenditem.rbclassItemi

  7. 使用canal同步MySQL数据到ES - 2

    文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co

  8. ruby-on-rails - 在 haml View 中重构条件 - 2

    除了可访问性标准不鼓励使用这一事实指向当前页面的链接,我应该怎么做重构以下View代码?#navigation%ul.tabbed-ifcurrent_page?(new_profile_path)%li{:class=>"current_page_item"}=link_tot("new_profile"),new_profile_path-else%li=link_tot("new_profile"),new_profile_path-ifcurrent_page?(profiles_path)%li{:class=>"current_page_item"}=link_tot("p

  9. ruby - Sinatra 找不到 View 目录 - 2

    我正在尝试以一种更类似于普通RubyGem结构的方式构建我的Sinatra应用程序。我有以下文件树:.├──app.rb├──config.ru├──Gemfile├──Gemfile.lock├──helpers│  ├──dbconfig.rb│  ├──functions.rb│  └──init.rb├──hidden│  └──Rakefile├──lib│  ├──admin.rb│  ├──api.rb│  ├──indexer.rb│  ├──init.rb│  └──magnet.rb├──models│  ├──init.rb│  ├──invite.rb│  ├─

  10. ruby-on-rails - 将 Amazon Simple Notification service SNS 与 ruby​​ 结合使用 - 2

    很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visitthehelpcenter.关闭9年前。我需要从基于ruby​​的应用程序使用AmazonSimpleNotificationService,但不知道从哪里开始。您对从哪里开始有什么建议吗?

随机推荐