[sql] select *를 사용하지 않는 이유는 무엇입니까?

많은 사람들이 선택 쿼리에서 원하는 각 열의 이름을 구체적으로 지정해야한다고 주장했습니다.

어쨌든 모든 열을 사용한다고 가정하면 왜 사용하지 SELECT *않습니까?

심지어 질문을 고려 * SQL 쿼리 – 선택 *보기 또는 선택 COL1, COL2에서 … colN이보기에서 *, 나는 약간 다른 관점에서 문제에 접근하고있어 같은이 정확한 중복 생각하지 않습니다.

우리의 원칙 중 하나는 시간이 지나기 전에 최적화하지 않는 것입니다. 이를 염두에두고 리소스 문제로 입증되거나 스키마가 거의 설정 될 때까지 사용 SELECT *하는 것이 선호되는 방법 인 것처럼 보입니다 . 우리가 알고 있듯이 개발이 완전히 완료 될 때까지 발생하지 않습니다.

즉, 사용하지 않는 가장 중요한 문제가 SELECT *있습니까?



답변

조기에 최적화하지 않는다는 인용의 본질은 간단하고 간단한 코드를 찾은 다음 프로파일 러를 사용하여 핫스팟을 지적하여 효율적으로 최적화 할 수 있다는 것입니다.

select *를 사용하면 프로파일 링이 불가능하므로 명확하고 간단한 코드를 작성하지 않으므로 인용의 정신에 위배됩니다. select *안티 패턴입니다.


따라서 열 선택은 조기 최적화가 아닙니다. 내 머리 꼭대기에서 몇 가지 ….

  1. SQL 문에 열을 지정하면 해당 열이 테이블에서 제거되고 쿼리가 실행되면 SQL 실행 엔진이 오류를 발생시킵니다.
  2. 해당 열이 사용되는 코드를 더 쉽게 스캔 할 수 있습니다.
  3. 최소한의 정보를 다시 가져 오려면 항상 쿼리를 작성해야합니다.
  4. 서수 열 액세스를 사용하는 경우 다른 사람들이 언급했듯이 select *를 사용해서는 안됩니다.
  5. SQL 문이 테이블을 조인하는 경우 select *는 조인에있는 모든 테이블의 모든 열을 제공합니다.

그 결과는 select *

  1. 응용 프로그램에서 사용하는 열이 불투명합니다
  2. DBA 및 해당 쿼리 프로파일 러가 응용 프로그램의 성능 저하를 도울 수 없습니다
  3. 변경 사항이 발생하면 코드가 더 부서지기 쉽습니다.
  4. 데이터베이스와 네트워크가 너무 많은 데이터를 가져 오기 때문에 어려움을 겪고 있습니다 (I / O)
  5. 데이터베이스 엔진 최적화는 최소 (논리적)에 관계없이 모든 데이터를 다시 가져 오므로 최소화됩니다.

올바른 SQL을 작성하는 것은 작성하는 것만 큼 쉽습니다 Select *. 실제 게으른 사람은 코드를 다시 방문하지 않고 코드를 다시 작성하고 싶지 않았기 때문에 적절한 SQL을 작성합니다. 그들은 모든 코드 비트에 대해 DBA에 설명하고 싶지 않습니다. 그들은 왜 응용 프로그램이 개처럼 실행되는지 고객에게 설명하고 싶지 않습니다.


답변

코드가 특정 순서의 열에 의존하는 경우 테이블이 변경되면 코드가 중단됩니다. 또한 *를 선택할 때 특히 테이블에 이진 필드가있는 경우 테이블에서 너무 많은 페치가 발생할 수 있습니다.

지금 모든 열을 사용한다고해서 다른 사람이 테이블에 추가 열을 추가하지 않는다는 의미는 아닙니다.

또한 테이블에 대한 메타 데이터를 가져 와서 *에있는 열을 알아야하기 때문에 계획 실행 캐싱에 오버 헤드를 추가합니다.


답변

주요한 이유 중 하나는 테이블에서 열을 추가 / 제거 할 경우 SELECT * 호출을 수행하는 모든 쿼리 / 프로 시저가 예상보다 많은 데이터 열을 가져 오는 것입니다.


답변

  1. 로터리 방식으로 가능한 한 엄격한 타이핑을 사용하는 것에 대한 모듈화 규칙을 위반하고 있습니다. 명시 적으로 거의 보편적으로 좋습니다.

  2. 이제 테이블의 모든 열이 필요하더라도 나중에 쿼리를 실행할 때마다 풀다운되어 성능이 저하 될 수있는 추가 열이 추가 될 수 있습니다. 성능이 저하되므로

    • 와이어를 통해 더 많은 데이터를 가져오고 있습니다. 과
    • 테이블 자체에서 조회를 수행하는 대신 인덱스에서 데이터를 바로 가져 오는 옵티마이 저의 기능 (인덱스의 일부인 열에 대한 쿼리의 경우)을 무시할 수 있기 때문입니다.

사용할 때 선택 *

QUERY를 기록 할 당시 존재했던 테이블의 모든 열이 필요하지 않고, 테이블의 모든 열을 명시 적으로 필요로하는 경우. 예를 들어, 테이블의 전체 내용을 표시하는 데 필요한 DB 관리 앱을 작성하는 경우 (어떤 일이 있었 든) 해당 방식을 사용할 수 있습니다.


답변

몇 가지 이유가 있습니다.

  1. 데이터베이스의 열 수가 변경되고 응용 프로그램에 특정 수가있을 것으로 예상되는 경우 …
  2. 데이터베이스의 열 순서가 변경되고 응용 프로그램에서 특정 순서를 기대하는 경우 …
  3. 메모리 오버 헤드. 8 개의 불필요한 INTEGER 열은 32 바이트의 낭비 된 메모리를 추가합니다. 그것은별로 들리지 않지만, 이것은 각 쿼리에 대한 것이고 INTEGER는 작은 열 유형 중 하나입니다 … 추가 열은 VARCHAR 또는 TEXT 열일 가능성이 더 높으므로 더 빨리 추가됩니다.
  4. 네트워크 오버 헤드. 메모리 오버 헤드와 관련하여 : 30,000 개의 쿼리를 발행하고 8 개의 불필요한 INTEGER 열이 있으면 960kB의 대역폭을 낭비했습니다. VARCHAR 및 TEXT 컬럼이 상당히 클 수 있습니다.

참고 : 위의 예제에서는 고정 크기가 4 바이트이므로 INTEGER를 선택했습니다.


답변

응용 프로그램에서 SELECT *를 사용하여 데이터를 가져오고 데이터베이스의 테이블 구조가 변경되면 (예 : 열 제거) 누락 된 필드를 참조하는 모든 위치에서 응용 프로그램이 실패합니다. 대신 쿼리에 모든 열을 포함 시키면 응용 프로그램이 처음에 데이터를 얻는 위치 (바람직하게)에서 깨져서 수정이 쉬워집니다.

즉, SELECT *가 바람직한 여러 가지 상황이 있습니다. 하나는 항상 전체 테이블을 다른 데이터베이스 (예 : SQL Server에서 DB2로)로 복제해야하는 상황입니다. 다른 하나는 일반적으로 테이블을 표시하도록 작성된 응용 프로그램입니다 (즉, 특정 테이블에 대한 지식이 없음).


답변

실제로 select *SQL Server 2005의 뷰에서 사용할 때 이상한 동작을 발견했습니다 .

다음 쿼리를 실행하면 무슨 뜻인지 알 수 있습니다.

IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[starTest]') AND type in (N'U'))
DROP TABLE [dbo].[starTest]
CREATE TABLE [dbo].[starTest](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [A] [varchar](50) NULL,
    [B] [varchar](50) NULL,
    [C] [varchar](50) NULL
) ON [PRIMARY]

GO

insert into dbo.starTest
select 'a1','b1','c1'
union all select 'a2','b2','c2'
union all select 'a3','b3','c3'

go
IF  EXISTS (SELECT * FROM sys.views WHERE object_id = OBJECT_ID(N'[dbo].[vStartest]'))
DROP VIEW [dbo].[vStartest]
go
create view dbo.vStartest as
select * from dbo.starTest
go

go
IF  EXISTS (SELECT * FROM sys.views WHERE object_id = OBJECT_ID(N'[dbo].[vExplicittest]'))
DROP VIEW [dbo].[vExplicittest]
go
create view dbo.[vExplicittest] as
select a,b,c from dbo.starTest
go


select a,b,c from dbo.vStartest
select a,b,c from dbo.vExplicitTest

IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[starTest]') AND type in (N'U'))
DROP TABLE [dbo].[starTest]
CREATE TABLE [dbo].[starTest](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [A] [varchar](50) NULL,
    [B] [varchar](50) NULL,
    [D] [varchar](50) NULL,
    [C] [varchar](50) NULL
) ON [PRIMARY]

GO

insert into dbo.starTest
select 'a1','b1','d1','c1'
union all select 'a2','b2','d2','c2'
union all select 'a3','b3','d3','c3'

select a,b,c from dbo.vStartest
select a,b,c from dbo.vExplicittest

마지막 2 개의 select 문의 결과를 비교하십시오. 나는 당신이 볼 것의 결과는 이름 대신 인덱스로 열을 참조 Select * .

뷰를 다시 빌드하면 다시 정상적으로 작동합니다.

편집하다

SQL Server 2005의 흥미로운 동작 인“테이블에서 선택 *”과“테이블에서 colA, colB 등 선택”과 같은 별도의 질문을 추가했습니다 .