많은 사람들이 선택 쿼리에서 원하는 각 열의 이름을 구체적으로 지정해야한다고 주장했습니다.
어쨌든 모든 열을 사용한다고 가정하면 왜 사용하지 SELECT *
않습니까?
심지어 질문을 고려 * SQL 쿼리 – 선택 *보기 또는 선택 COL1, COL2에서 … colN이보기에서 *, 나는 약간 다른 관점에서 문제에 접근하고있어 같은이 정확한 중복 생각하지 않습니다.
우리의 원칙 중 하나는 시간이 지나기 전에 최적화하지 않는 것입니다. 이를 염두에두고 리소스 문제로 입증되거나 스키마가 거의 설정 될 때까지 사용 SELECT *
하는 것이 선호되는 방법 인 것처럼 보입니다 . 우리가 알고 있듯이 개발이 완전히 완료 될 때까지 발생하지 않습니다.
즉, 사용하지 않는 가장 중요한 문제가 SELECT *
있습니까?
답변
조기에 최적화하지 않는다는 인용의 본질은 간단하고 간단한 코드를 찾은 다음 프로파일 러를 사용하여 핫스팟을 지적하여 효율적으로 최적화 할 수 있다는 것입니다.
select *를 사용하면 프로파일 링이 불가능하므로 명확하고 간단한 코드를 작성하지 않으므로 인용의 정신에 위배됩니다. select *
안티 패턴입니다.
따라서 열 선택은 조기 최적화가 아닙니다. 내 머리 꼭대기에서 몇 가지 ….
- SQL 문에 열을 지정하면 해당 열이 테이블에서 제거되고 쿼리가 실행되면 SQL 실행 엔진이 오류를 발생시킵니다.
- 해당 열이 사용되는 코드를 더 쉽게 스캔 할 수 있습니다.
- 최소한의 정보를 다시 가져 오려면 항상 쿼리를 작성해야합니다.
- 서수 열 액세스를 사용하는 경우 다른 사람들이 언급했듯이 select *를 사용해서는 안됩니다.
- SQL 문이 테이블을 조인하는 경우 select *는 조인에있는 모든 테이블의 모든 열을 제공합니다.
그 결과는 select *
…
- 응용 프로그램에서 사용하는 열이 불투명합니다
- DBA 및 해당 쿼리 프로파일 러가 응용 프로그램의 성능 저하를 도울 수 없습니다
- 변경 사항이 발생하면 코드가 더 부서지기 쉽습니다.
- 데이터베이스와 네트워크가 너무 많은 데이터를 가져 오기 때문에 어려움을 겪고 있습니다 (I / O)
- 데이터베이스 엔진 최적화는 최소 (논리적)에 관계없이 모든 데이터를 다시 가져 오므로 최소화됩니다.
올바른 SQL을 작성하는 것은 작성하는 것만 큼 쉽습니다 Select *
. 실제 게으른 사람은 코드를 다시 방문하지 않고 코드를 다시 작성하고 싶지 않았기 때문에 적절한 SQL을 작성합니다. 그들은 모든 코드 비트에 대해 DBA에 설명하고 싶지 않습니다. 그들은 왜 응용 프로그램이 개처럼 실행되는지 고객에게 설명하고 싶지 않습니다.
답변
코드가 특정 순서의 열에 의존하는 경우 테이블이 변경되면 코드가 중단됩니다. 또한 *를 선택할 때 특히 테이블에 이진 필드가있는 경우 테이블에서 너무 많은 페치가 발생할 수 있습니다.
지금 모든 열을 사용한다고해서 다른 사람이 테이블에 추가 열을 추가하지 않는다는 의미는 아닙니다.
또한 테이블에 대한 메타 데이터를 가져 와서 *에있는 열을 알아야하기 때문에 계획 실행 캐싱에 오버 헤드를 추가합니다.
답변
주요한 이유 중 하나는 테이블에서 열을 추가 / 제거 할 경우 SELECT * 호출을 수행하는 모든 쿼리 / 프로 시저가 예상보다 많은 데이터 열을 가져 오는 것입니다.
답변
-
로터리 방식으로 가능한 한 엄격한 타이핑을 사용하는 것에 대한 모듈화 규칙을 위반하고 있습니다. 명시 적으로 거의 보편적으로 좋습니다.
-
이제 테이블의 모든 열이 필요하더라도 나중에 쿼리를 실행할 때마다 풀다운되어 성능이 저하 될 수있는 추가 열이 추가 될 수 있습니다. 성능이 저하되므로
- 와이어를 통해 더 많은 데이터를 가져오고 있습니다. 과
- 테이블 자체에서 조회를 수행하는 대신 인덱스에서 데이터를 바로 가져 오는 옵티마이 저의 기능 (인덱스의 일부인 열에 대한 쿼리의 경우)을 무시할 수 있기 때문입니다.
사용할 때 선택 *
QUERY를 기록 할 당시 존재했던 테이블의 모든 열이 필요하지 않고, 테이블의 모든 열을 명시 적으로 필요로하는 경우. 예를 들어, 테이블의 전체 내용을 표시하는 데 필요한 DB 관리 앱을 작성하는 경우 (어떤 일이 있었 든) 해당 방식을 사용할 수 있습니다.
답변
몇 가지 이유가 있습니다.
- 데이터베이스의 열 수가 변경되고 응용 프로그램에 특정 수가있을 것으로 예상되는 경우 …
- 데이터베이스의 열 순서가 변경되고 응용 프로그램에서 특정 순서를 기대하는 경우 …
- 메모리 오버 헤드. 8 개의 불필요한 INTEGER 열은 32 바이트의 낭비 된 메모리를 추가합니다. 그것은별로 들리지 않지만, 이것은 각 쿼리에 대한 것이고 INTEGER는 작은 열 유형 중 하나입니다 … 추가 열은 VARCHAR 또는 TEXT 열일 가능성이 더 높으므로 더 빨리 추가됩니다.
- 네트워크 오버 헤드. 메모리 오버 헤드와 관련하여 : 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 등 선택”과 같은 별도의 질문을 추가했습니다 .