【问题标题】:why there is a performance difference between single column select and multi column select为什么单列选择和多列选择之间存在性能差异
【发布时间】:2014-10-29 00:09:07
【问题描述】:

我有超过 10 列的表 Report,其中除自动增量 id 之外的每个字段都是 varchar。 表中任何一行的最大大小约为 80000 字节。

我观察到以下 2 个查询之间存在相当大的差异,其中服务器和客户端都在同一系统上(大约 150 万行)(列名也有索引)

select * from Report;

&

select name from Report;

我经历了其他 stackoverflow 问题,其中 Ans 建议

“选择特定列更好的一个原因是它 提高 SQL Server 可以访问数据的可能性 索引而不是查询表数据。 "

我的问题是:

1) 即使在使用索引时,我们也需要从实际的 DB(即磁盘)中读取,所以相同的磁盘 I/O 将 当我们选择单列或多列时执行(比如说使用 *)。

2)有人可以用很少的内部知识来解释为什么单列选择和多列选择之间存在差异。 据我了解,数据库尝试将完整的行存储在同一磁盘扇区中。

让我们说一些像用户表这样的查询

select first_name from user & 
select first_name, age from user 

3) DB 是否执行相同的磁盘 I/O(对于上述查询),或者磁盘 I/O 可能不同,如果用户表有超过 10 列并且我们选择 5~8 列仍然磁盘 I/O 怎么办一样吗?

在其他 Ans 中已经读到使用 select * 是不可取的,它可能会导致视图和维护问题(将新列添加到 DB 时的情况)

这可能是一个愚蠢的问题,因为仍在学习数据库(新手到主题)。如果某些问题已经在任何地方得到解答,请提供链接。

【问题讨论】:

  • 你的假设是错误的。如果索引包含所有选定的列,SQL Server 将不会访问磁盘来获取它们。
  • stackoverflow.com/questions/609343/… 但 Panagiotis 给出的实际答案完美地击中了头部。

标签: mysql sql sql-server database postgresql


【解决方案1】:

你的假设是错误的。如果索引包含所有选定的列,SQL Server 将不会从磁盘中获取它们,它会从索引数据中检索它们。与数据页相比,索引更可能保存在内存中,因此查询可能根本不必访问磁盘。

如果您的select 包含您不需要但未包含在任何索引中的列,则服务器将不得不无缘无故地从磁盘读取数据。

另一件确实发生变化的是网络 I/O。生产服务器每分钟可能必须为数百个客户端提供数千个查询。在数据中包含无用的列会影响所有客户端。如果考虑到客户端可能有几千个的流行网站中使用的服务器,情况会更糟。

【讨论】:

  • 如果选择的列/列没有被索引,那么单列选择和多列选择有什么区别吗?我的 (2)、(3) 问题在没有索引的情况下是否有效?
【解决方案2】:

一个可能的答案是,如果它需要的数据在索引中,MySQL 就不会费心去读取表。如果名称被索引,那么这可能是有意义的。

Anpther 只是传输结果所需的时间,这可能很重要,具体取决于您的设置/网络速度等。

【讨论】:

    【解决方案3】:

    问题是TOAST

    长数据值可以将这些值压缩和/或存储在行的其余部分之外。这称为 TOAST。

    如果您请求的数据值已被 TOASTED,数据库必须停止获取它并解压缩它,这需要时间。

    另一方面,如果您避免选择不需要的列,则不必获取这些值。因为现在最大的值是离线的,所以行的主要部分被更紧密地打包和更好地缓存,从而提供了更好的性能。

    一般来说,最大值也是最不可能需要的值,所以这通常是一个很好的权衡。

    故事的寓意是当性能对您很重要时,不要请求您不需要的列,尤其是当这些列可能具有较大值时。

    PostgreSQL 确实有 index-only-scans,但除非表中的每一列都包含在单个索引中,否则不可能执行 index-only-scan 来支持select *,所以这不是这里解释一下。

    【讨论】:

    • 假设行是否在限制范围内(通常为 8 kB),这样就不会被 Toasted,那么单列选择或多列选择有什么区别(如果我们没有索引选择列)。
    猜你喜欢
    • 2013-05-21
    • 1970-01-01
    • 1970-01-01
    • 2012-02-09
    • 1970-01-01
    • 2013-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多