Programing

select * vs select column

crosscheck 2020. 7. 20. 07:37
반응형

select * vs select column


2/3 열이 필요 SELECT *하고 select 쿼리에서 해당 열을 제공하는 대신 쿼리하면 더 많거나 적은 I / O 또는 메모리와 관련된 성능 저하가 있습니까?

필요없이 *를 선택하면 네트워크 오버 헤드가 발생할 수 있습니다.

그러나 선택 작업에서 데이터베이스 엔진은 항상 디스크에서 원자 튜플을 가져 옵니까, 아니면 선택 작업에서 요청한 열만 가져 옵니까?

항상 튜플을 가져 오면 I / O 오버 헤드는 동일합니다.

동시에 튜플을 가져 오는 경우 요청 된 열을 튜플에서 제거하기 위해 메모리 소비가있을 수 있습니다.

이 경우 selectColumn은 select *보다 많은 메모리 오버 헤드를 갖습니다.


항상 튜플을 가져옵니다 (테이블이 세로로 분할 된 경우-열 조각으로 나뉘어 진 경우 제외). 질문에 대답하기 위해 성능 측면에서 중요하지 않습니다. 그러나 여러 가지 다른 이유로 (아래) 항상 원하는 열을 이름별로 선택해야합니다.

모든 벤더 (테이블 데이터 포함)에 대한 기본 온 디스크 스토리지 구조는 정의 된 I / O 페이지 (예 : SQL Server의 각 페이지는 다음과 같습니다 )를 기반으로하기 때문에 항상 튜플을 가져옵니다. 8 킬로바이트). 그리고 모든 I / O 읽기 또는 쓰기는 페이지별로 이루어집니다. 즉, 모든 쓰기 또는 읽기는 완전한 데이터 페이지입니다.

이러한 기본적인 구조적 제약으로 인해 데이터베이스의 각 데이터 행은 항상 하나의 페이지에만 있어야합니다. 여러 페이지의 데이터에 걸쳐있을 수 없습니다 (실제 blob 데이터가 별도의 Page-chunks에 저장되고 실제 테이블 행 열은 포인터 만 가져 오는 blob과 같은 특수 항목 제외). 그러나 이러한 예외는 예외 일 뿐이며 특수한 경우 (특별한 유형의 데이터 또는 특수한 상황에 대한 특정 최적화의 경우)를 제외하고는 일반적으로 적용되지 않습니다
. 이러한 특수한 경우에도 일반적으로 실제 테이블 데이터 행 ( Blob의 실제 데이터에 대한 포인터 또는 기타) 단일 IO 페이지에 저장해야합니다 ...

예외. Select *OK 인 유일한 장소 는 다음과 같이 Exists또는 Not Existspredicate 절 다음의 하위 쿼리 에 있습니다.

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

편집 : @ Mike Sherer 의견을 해결하기 위해 예, 기술적으로는 특별한 경우에 대한 약간의 정의와 미학적으로 사실입니다. 첫째, 요청 된 컬럼 세트가 일부 인덱스에 저장된 컬럼의 서브 세트 인 경우에도 쿼리 프로세서는 동일한 이유로 요청 된 컬럼뿐만 아니라 해당 인덱스에 저장된 모든 컬럼을 페치해야합니다. 모든 I / O는 페이지 및 인덱스 데이터는 테이블 데이터와 마찬가지로 IO 페이지에 저장됩니다. 따라서 인덱스 페이지에 "tuple"을 인덱스에 저장된 열 세트로 정의해도 명령문은 여전히 ​​유효합니다.
요점은 요청한 것이 아니라 I / O 페이지에 저장된 내용을 기반으로 데이터를 가져오고 기본 테이블 I / O 페이지에 액세스하는지 또는 인덱스에 액세스하는지 여부에 따라 미적으로 사실입니다. I / O 페이지.

를 사용하지 않는 다른 이유 는 왜 유해한 것으로 간주됩니까?를Select * 참조하십시오 . :SELECT *


SELECT *프로덕션 코드에서 절대 사용해서는 안되는 몇 가지 이유가 있습니다 .

  • 데이터베이스에 원하는 힌트를 제공하지 않기 때문에 먼저 해당 테이블의 열을 결정하기 위해 테이블의 정의를 확인해야합니다. 이 조회는 단일 쿼리에서 많은 시간이 걸리지 않지만 시간이 지남에 따라 추가됩니다.

  • 열의 2/3 만 필요한 경우 디스크에서 검색하여 네트워크를 통해 전송해야하는 1/3의 데이터를 너무 많이 선택합니다.

  • 데이터의 특정 측면 (예 : 반환 된 열의 순서)에 의존하기 시작하면 테이블이 재구성되고 새 열이 추가되거나 기존 열이 제거되면 놀라 울 수 있습니다.

  • SQL Server에서 (다른 데이터베이스에 대해서는 잘 모름) 열의 하위 집합이 필요한 경우 클러스터되지 않은 인덱스가 해당 요청을 처리 할 가능성이 항상 있습니다 (필요한 모든 열 포함). 를 사용하면 시작 SELECT *부터 바로 그 가능성을 포기할 수 있습니다. 이 경우 인덱스 페이지에서 데이터가 검색되므로 (필요한 모든 열이 포함 된 경우) 디스크 I / O 메모리 오버 헤드는 SELECT *....쿼리 수행에 비해 훨씬 적습니다 .

예, 처음에는 약간 더 타이핑해야합니다 ( SQL Server 용 SQL Prompt 와 같은 도구 가 도움이 될 것입니다). 그러나 예외없이 규칙이있는 경우는 실제로는 프로덕션 코드에서 SELECT *를 사용하지 마십시오. 이제까지.


당신은해야한다 항상 에만 select열 실제로 필요. 더 적은 것보다 적은 것을 선택하는 것이 결코 효율적이지 않으며, 인덱스별로 클라이언트 열의 결과 열에 액세스 한 다음 테이블에 새 열을 추가하여 해당 인덱스가 잘못되도록하는 등 예기치 않은 부작용이 줄어 듭니다.

[편집] : 액세스 중입니다. 어리석은 두뇌는 여전히 깨어있다.


큰 얼룩을 저장하지 않는 한 성능은 문제가되지 않습니다. SELECT *를 사용하지 않는 가장 큰 이유는 반환 된 행을 튜플로 사용하는 경우 스키마가 지정하는 순서에 따라 열이 다시 나타나며 변경이 있으면 모든 코드를 수정해야하기 때문입니다.

반면에 사전 스타일 액세스를 사용하는 경우 항상 이름으로 열에 액세스하기 때문에 열의 순서는 중요하지 않습니다.


이것은 즉시 내가 사용하고있는 테이블을 생각합니다 blob. 그것은 보통 몇 Mb초 크기의 JPEG 이미지를 포함했습니다 .

말할 것도없이 SELECT필자가 실제로 필요 하지 않은 한 그 칼럼 은 없었 습니다. 특히 여러 행을 선택할 때 그 데이터가 떠 다니는 것은 번거로운 일이었습니다.

그러나 나는 그렇지 않으면 일반적으로 테이블의 모든 열을 쿼리한다는 것을 인정합니다.


SQL을 선택하는 동안 DB는 SELECT a, b, c의 SELECT * 여부에 관계없이 항상 테이블의 메타 데이터를 참조합니다. 왜? 시스템에서 테이블의 구조와 레이아웃에 대한 정보가있는 곳이되어야합니다.

두 가지 이유로이 정보를 읽어야합니다. 하나, 단순히 문장을 컴파일합니다. 최소한 기존 테이블을 지정해야합니다. 또한 명령문이 마지막으로 실행 된 이후 데이터베이스 구조가 변경되었을 수 있습니다.

이제 DB 메타 데이터는 시스템에 캐시되지만 여전히 처리해야합니다.

다음으로 메타 데이터는 쿼리 계획을 생성하는 데 사용됩니다. 이것은 명령문이 컴파일 될 때마다 발생합니다. 다시 말하지만, 이것은 캐시 된 메타 데이터에 대해 실행되지만 항상 수행됩니다.

The only time this processing is not done is when the DB is using a pre-compiled query, or has cached a previous query. This is the argument for using binding parameters rather than literal SQL. "SELECT * FROM TABLE WHERE key = 1" is a different query than "SELECT * FROM TABLE WHERE key = ?" and the "1" is bound on the call.

DBs rely heavily on page caching for there work. Many modern DBs are small enough to fit completely in memory (or, perhaps I should say, modern memory is large enough to fit many DBs). Then your primary I/O cost on the back end is logging and page flushes.

However, if you're still hitting the disk for your DB, a primary optimization done by many systems is to rely on the data in indexes, rather than the tables themselves.

If you have:

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);

Then if you do "SELECT id, name FROM customer WHERE id = 1", it is very likely that you DB will pull this data from the index, rather than from the tables.

Why? It will likely use the index anyway to satisfy the query (vs a table scan), and even though 'name' isn't used in the where clause, that index will still be the best option for the query.

Now the database has all of the data it needs to satisfy the query, so there's no reason to hit the table pages themselves. Using the index results in less disk traffic since you have a higher density of rows in the index vs the table in general.

This is a hand wavy explanation of a specific optimization technique used by some databases. Many have several optimization and tuning techniques.

In the end, SELECT * is useful for dynamic queries you have to type by hand, I'd never use it for "real code". Identification of individual columns gives the DB more information that it can use to optimize the query, and gives you better control in your code against schema changes, etc.


I think there is no exact answer for your question, because you have pondering performance and facility of maintain your apps. Select column is more performatic of select *, but if you is developing an oriented object system, then you will like use object.properties and you can need a properties in any part of apps, then you will need write more methods to get properties in special situations if you don't use select * and populate all properties. Your apps need have a good performance using select * and in some case you will need use select column to improve performance. Then you will have the better of two worlds, facility to write and maintain apps and performance when you need performance.


The accepted answer here is wrong. I came across this when another question was closed as a duplicate of this (while I was still writing my answer - grr - hence the SQL below references the other question).

You should always use SELECT attribute, attribute.... NOT SELECT *

It's primarily for performance issues.

SELECT name FROM users WHERE name='John';

Is not a very useful example. Consider instead:

SELECT telephone FROM users WHERE name='John';

If there's an index on (name, telephone) then the query can be resolved without having to look up the relevant values from the table - there is a covering index.

Further, suppose the table has a BLOB containing a picture of the user, and an uploaded CV, and a spreadsheet... using SELECT * will willpull all this information back into the DBMS buffers (forcing out other useful information from the cache). Then it will all be sent to client using up time on the network and memory on the client for data which is redundant.

It can also cause functional issues if the client retrieves the data as an enumerated array (such as PHP's mysql_fetch_array($x, MYSQL_NUM)). Maybe when the code was written 'telephone' was the third column to be returned by SELECT *, but then someone comes along and decides to add an email address to the table, positioned before 'telephone'. The desired field is now shifted to the 4th column.


There are reasons for doing things either way. I use SELECT * a lot on PostgreSQL because there are a lot of things you can do with SELECT * in PostgreSQL that you can't do with an explicit column list, particularly when in stored procedures. Similarly in Informix, SELECT * over an inherited table tree can give you jagged rows while an explicit column list cannot because additional columns in child tables are returned as well.

The main reason why I do this in PostgreSQL is that it ensures that I get a well-formed type specific to a table. This allows me to take the results and use them as the table type in PostgreSQL. This also allows for many more options in the query than a rigid column list would.

On the other hand, a rigid column list gives you an application-level check that db schemas haven't changed in certain ways and this can be helpful. (I do such checks on another level.)

As for performance, I tend to use VIEWs and stored procedures returning types (and then a column list inside the stored procedure). This gives me control over what types are returned.

But keep in mind I am using SELECT * usually against an abstraction layer rather than base tables.


Reference taken from this article:

Without SELECT *: When you are using ” SELECT * ” at that time you are selecting more columns from the database and some of this column might not be used by your application. This will create extra cost and load on database system and more data travel across the network.

With SELECT *: If you have special requirements and created dynamic environment when add or delete column automatically handle by application code. In this special case you don’t require to change application and database code and this will automatically affect on production environment. In this case you can use “SELECT *”.


Just to add a nuance to the discussion which I don't see here: In terms of I/O, if you're using a database with column-oriented storage you can do A LOT less I/O if you only query for certain columns. As we move to SSDs the benefits may be a bit smaller vs. row-oriented storage but there's a) only reading the blocks that contain columns you care about b) compression, which generally greatly reduces the size of the data on disk and therefore the volume of data read from disk.

If you're not familiar with column-oriented storage, one implementation for Postgres comes from Citus Data, another is Greenplum, another Paraccel, another (loosely speaking) is Amazon Redshift. For MySQL there's Infobright, the now-nigh-defunct InfiniDB. Other commercial offerings include Vertica from HP, Sybase IQ, Teradata...


select * from table1 INTERSECT  select * from table2

equal

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

참고URL : https://stackoverflow.com/questions/3180375/select-vs-select-column

반응형