select* vsselect列

如果我只需要2/3列,我查询SELECT *而不是在select查询中提供这些列。 有更多/更less的I / O或内存有任何性能下降?

networking开销可能会出现,如果我select*没有需要。

但是在select操作中,数据库引擎是否总是从磁盘中提取primefaces元组? 或者只拉取select操作中请求的那些列。

如果它总是拉一个元组,那么I / O开销是相同的。

与此同时。 从元组中删除请求的列可能会消耗内存。 如果它拉出一个元组。

所以,如果是这样的话selectsomeColumn将有更多的内存开销比select*

它总是拉取一个元组(除了表格被垂直分割的情况以外 – 分成多个分段),所以要回答你所问的问题,从性能的angular度来看并不重要。 但是,由于许多其他原因,(下面),您应该总是select所需的专栏,按名称。

它总是拉一个元组,因为(在我熟悉的每个供应商的RDBMS中,所有事物(包括表数据)的底层磁盘存储结构都是基于定义的I / O页面的 (例如,在SQL Server中,每个页面是8千字节,每个I / O读或写都是由页面组成的,也就是每个写或读都是一个完整的数据页面。

由于这种潜在的结构性约束,结果是数据库中的每一行数据必须总是在一个页面上。 它不能跨越多个数据页面(除了像blob这样的特殊事物,其中实际的blob数据存储在不同的页面块中,并且实际的表格行列只有一个指针…)。 但是这些例外就是这样的例外情况,除了特殊情况(特殊types的数据或特殊情况下的特定优化)
即使在这些特殊情况下,一般情况下,实际的表行数据本身(包含指向Blob的实际数据的指针,或其他),它必须存储在单个IO页上…

例外。 Select *是OK的唯一地方是在ExistsNot Exists谓词子句之后的子查询中,如下所示:

  Select colA, colB From table1 t1 Where Exists (Select * From Table2 Where column = t1.colA) 

编辑:为了解决@Mike Sherer的评论,是的,这是真的,无论是在技术上,还是为您的特殊情况和美学定义。 首先,即使所请求的列是某些索引中存储的列的子集,查询处理器也必须获取存储在该索引中的每一列,而不仅仅是所请求的列,原因相同 – 所有I / O必须在页面和索引数据就像表格数据一样存储在IO Pages中。 因此,如果将索引页面的“元组”定义为存储在索引中的一组列,则该语句仍然是真实的。
而且这个语句在美学上是真实的,因为重点在于它根据存储在I / O页面中的内容来获取数据,而不是基于你要求的内容,而不pipe你是在访问基本表I / O页面还是索引I / O页面。

由于其他原因不使用Select * ,请参阅为什么SELECT *被认为是有害的? :

有几个原因,你永远不应该(永远不会)在生产代码中使用SELECT *

  • 因为你没有给你的数据库提供任何你想要的提示,它首先需要检查表的定义,以确定该表的列。 这种查找将花费一些时间 – 在单个查询中没有多less – 但是随着时间的推移而增加

  • 如果你只需要2/3的列,那么你select的数据太多了,需要从磁盘中检索并通过networking发送

  • 如果您开始依赖数据的某些方面(例如返回的列的顺序),那么一旦表格被重新组织并添加了新列(或现有的列),就会产生令人不愉快的惊喜。

  • 在SQL Server中(不确定其他数据库),如果你需要列的一个子集,非聚集索引总是有可能覆盖这个请求(包含所有需要的列)。 有了SELECT * ,您就可以从一开始就放弃这种可能性。 在这种特殊情况下,数据将从索引页(如果这些索引页包含所有必要的列)中检索,因此与执行SELECT *....查询相比,磁盘I / O 内存开销将小得多。

是的,它最初需要多一点打字( SQL提示 SQL Server的工具甚至可以帮助你) – 但是这是一个没有任何exception的规则:在生产代码中不要使用SELECT *。 EVER。

您应该始终select您实际需要的列。 select更less而不是更less效率,而且还会遇到更less的意外副作用 – 例如通过索引访问客户端的结果列,然后通过在表中添加新列来使这些索引变得不正确。

意味着访问。 愚蠢的大脑还在醒来。

除非你存储大块,否则性能不是问题。 不使用SELECT *的一个重要原因是,如果您将返回的行作为元组使用,那么这些列按照架构恰好指定的顺序返回,如果发生更改,则必须修复所有代码。

另一方面,如果你使用字典式的访问方式,列的返回顺序并不重要,因为你总是按名字访问它们。

这立即让我想到了一个我正在使用的表格,其中包含一个blobtypes的列; 它通常包含一个JPEG图像,几Mb的大小。

不用说,我没有SELECT那个专栏,除非我真的需要它。 让数据浮出水面 – 特别是当我select多行时 – 只是一个麻烦。

但是,我会承认,否则我通常会查询表中的所有列。

在SQLselect过程中,数据库总是要引用该表的元数据,而不pipe它是SELECT * for SELECT a,b,c …为什么? 因为这是系统表格结构和布局的信息。

它必须阅读这些信息有两个原因。 一,简单地编制声明。 它需要确保至less指定一个现有的表。 而且,自上次执行语句以来,数据库结构可能已经更改。

显然,数据库元数据被caching在系统中,但仍然需要处理。

接下来,元数据用于生成查询计划。 每次编译语句时都会发生这种情况。 再一次,这是针对caching的元数据运行的,但总是完成。

这个处理没有完成的唯一时间是数据库正在使用预编译的查询,或者caching了以前的查询。 这是使用绑定参数而不是文字SQL的参数。 “SELECT * FROM TABLE WHERE key = 1”是与“SELECT * FROM TABLE WHERE key =?”不同的查询。 并在通话中绑定“1”。

数据库在很大程度上依赖于页面caching。 许多现代数据库足够小,可以完全适应内存(或者我应该说,现代内存足够大,可以容纳许多数据库)。 那么后端的主要I / O成本就是日志logging和页面刷新。

但是,如果您仍然在为数据库创build磁盘,那么许多系统所做的主要优化就是依靠索引中的数据,而不是表格本身。

如果你有:

 CREATE TABLE customer ( id INTEGER NOT NULL PRIMARY KEY, name VARCHAR(150) NOT NULL, city VARCHAR(30), state VARCHAR(30), zip VARCHAR(10)); CREATE INDEX k1_customer ON customer(id, name); 

然后,如果你做“SELECT id,name FROM customer WHERE id = 1”,那么很可能你的数据库将从索引中取出这些数据,而不是从表中取出。

为什么? 它可能会使用索引满足查询(与表扫描),即使'名称'没有在where子句中使用,该索引仍然是查询的最佳select。

现在数据库拥有了满足查询所需的全部数据,所以没有理由自己去查看表格页面。 使用索引会导致更less的磁盘stream量,因为索引中的行的密度与表中的行密度较高。

这是对某些数据库所使用的特定优化技术的手动波形解释。 许多人有几个优化和调整技术。

最后,SELECT *对于您必须手动input的dynamic查询非常有用,我绝不会将它用于“真实代码”。 单个列的标识为DB提供了可用于优化查询的更多信息,并使您可以更好地控制代码,防止模式更改等。

我认为你的问题没有确切的答案,因为你有考虑维护你的应用程序的性能和设施。 Select columnselect *更多performance,但是如果你正在开发一个面向对象的系统,那么你会喜欢使用object.properties ,你可以在应用程序的任何部分需要一个属性,那么你将需要编写更多的方法来获取属性特殊情况下,如果你不使用select *并填充所有属性。 您的应用程序需要使用select *才能获得良好的性能,在某些情况下,您需要使用select列来提高性能。 那么当你需要性能的时候,你将拥有两个更好的世界,可以编写和维护应用程序和性能。

这里接受的答案是错误的。 我遇到这个时, 另一个问题被closures作为这个副本(当我还在写我的答案 – grr – 因此下面的SQL引用另一个问题)。

你应该总是使用SELECT属性,属性….不select*

这主要是为了性能问题。

SELECT name FROM users WHERE name ='John';

这不是一个非常有用的例子。 换而言之:

 SELECT telephone FROM users WHERE name='John'; 

如果(姓名,电话)上有一个索引,那么查询可以解决,而不必从表中查找相关的值 – 有一个覆盖索引。

此外,假设表中有一个包含用户图片的BLOB,一个上传的CV和一个电子表格……使用SELECT *会将所有这些信息重新存入DBMS缓冲区(从caching中强制出其他有用的信息)。 然后它将全部被发送到客户端,使用networking上的时间和客户端上的存储器来获得冗余的数据。

如果客户端将数据作为枚举数组(如PHP的mysql_fetch_array($ x,MYSQL_NUM))进行检索,则也会导致function问题。 也许当代码被写成“电话”是由SELECT *返回的第三列时,但是随后有人出现并决定将电子邮件地址添加到位于“电话”之前的表格中。 所需的字段现在被转移到第四列。

无论做什么都有理由。 我在PostgreSQL上使用了SELECT *,因为在PostgreSQL里有很多你可以用SELECT *做的事情,你不能使用明确的列列表,特别是在存储过程中。 同样,在Informix中,SELECT *在inheritance的表树上可以给锯齿状行,而显式列表不能返回,因为子表中的其他列也会返回。

我在PostgreSQL中做这个的主要原因是它确保我得到一个特定于表格的格式良好的types。 这使我能够将结果作为PostgreSQL中的表types使用。 这也允许在查询中有更多的选项,而不是一个固定的列列表。

另一方面,一个刚性的列列表给你一个应用程序级别的检查数据库模式没有改变在某些方面,这可能是有帮助的。 (我在另一层面上进行这种检查。)

至于性能,我倾向于使用VIEWs和存储过程返回types(然后存储过程中的列列表)。 这使我能够控制返回的types。

但请记住,我使用SELECT *通常是针对抽象层而不是基表。

从这篇文章引用:

没有SELECT *:当你使用“SELECT *”的时候,你从数据库中select了更多的列,这个列中的一些可能不会被你的应用程序使用。 这将在数​​据库系统上产生额外的成本和负担,并且在networking上传输更多的数据。

使用SELECT *:如果您有特殊要求,创builddynamic环境时添加或删除列自动处理的应用程序代码。 在这种特殊情况下,您不需要更改应用程序和数据库代码,这会自动影响生产环境。 在这种情况下,你可以使用“SELECT *”。

只是为了增加一个细微的差别,我没有在这里看到:就I / O而言,如果你使用的是一个面向列存储的数据库,那么你可以做很less的I / O操作列。 随着我们转移到固态硬盘,与面向行的存储相比,好处可能会小一些,但是a)只读取包含您关心的列的块b)压缩,这通常会大大减less磁盘上的数据大小,从磁盘读取的数据量。

如果您不熟悉列式存储,那么Postgres的一个实现来自Citus Data,另一个是Greenplum,另一个是Paraccel,另一个(松散地说)是Amazon Redshift。 对于MySQL而言,Infobright是现在已经解决的InfiniDB。 其他商业产品包括惠普的Vertica,Sybase IQ,Teradata …

 select * from table1 INTERSECT select * from table2 

等于

 select distinct t1 from table1 where Exists (select t2 from table2 where table1.t1 = t2 )