뷰를 구축하기 위해 '*'를 사용하는 것이 왜 좋지 않습니까?

StackOverflow https://stackoverflow.com/questions/262450

  •  06-07-2019
  •  | 
  •  

문제

뷰를 구축하기 위해 '*'를 사용하는 것이 왜 좋지 않습니까?

복잡한 조인이 있고 모든 필드가 어딘가에서 사용될 수 있다고 가정합니다.

그런 다음 필요한 필드를 선택하기만 하면 됩니다.

SELECT field1, field2 FROM aview WHERE ...

뷰 "aview"는 다음과 같을 수 있습니다. SELECT table1.*, table2.* ... FROM table1 INNER JOIN table2 ...

table1과 table2에서 두 필드의 이름이 같으면 문제가 발생합니다.

이것이 뷰에서 '*'를 사용하는 것이 나쁜 이유일까요?

'*'를 사용하면 정보가 있으므로 다른 컨텍스트에서 뷰를 사용할 수 있습니다.

내가 무엇을 놓치고 있나요?

문안 인사

도움이 되었습니까?

해결책

소프트웨어에는 "나쁘다"는 소프트웨어가 많다고 생각하지 않지만 나쁜 방식으로 오용되는 많은 것들이 있습니다 :-)

당신이주는 예는 * * 당신이 기대하는 것을주지 않을 수있는 이유이며, 다른 사람들이 있다고 생각합니다. 예를 들어, 기본 테이블이 변경되면 열이 추가되거나 제거되면 사용하는 뷰는 계속 유효하지만 사용하는 응용 프로그램을 중단 할 수 있습니다. 당신의 견해가 열을 명시 적으로 명명했다면 스키마를 변경할 때 누군가가 문제를 발견 할 가능성이 더 높았습니다.

반면에, 당신은 실제로 할 수 있습니다 원하다 기본 테이블에 대한 모든 변경 사항을 뻔뻔스럽게 받아들이려는 귀하의 견해는 A *가 원하는 것입니다.

업데이트: OP에 특정 데이터베이스 공급 업체를 염두에두고 있는지는 모르겠지만 이제 내 마지막 발언이 모든 유형에 맞지 않는다는 것이 분명합니다. 나는 이것을 지적 한 것에 대해 user12861과 Jonny Leeds에게 빚을지고 있으며, 제 답변을 편집하는 데 6 년이 걸려서 죄송합니다.

다른 팁

여기에있는 많은 의견이 매우 우수하고 기본 테이블이 변경되면 오류 또는 다른 결과를 유발하는 것과 같은 쿼리에서 와일드 카드를 사용하는 일반적인 문제 중 하나를 참조하십시오. 테이블의 모든 열을 가져 오는 쿼리는 실제로 필요한 열만 가져 오는 쿼리만큼 효율적이지 않은 경향이 있습니다. 물론, 모든 열이 필요할 때의 시간이 있으며, 특히 큰 테이블에서 모든 열을 참조 해야하는 주요 PIA이지만, 하위 집합 만 필요한 경우 필요한 것보다 더 많은 열로 쿼리를 써 버리는 이유가 있습니다.

또 다른 이유 "*"시야뿐만 아니라 쿼리에서는 위험이 위험합니다. 열은 기본 테이블에서 이름 또는 변경 위치를 변경할 수 있다는 것입니다. 와일드 카드를 사용하면 뷰를 사용하면 변경이 변경 될 필요없이 이러한 변경 사항을 쉽게 수용 할 수 있습니다. 결과 세트의 위치 또는 열 이름으로 키를 키우는 결과 세트를 리턴하는 동적 언어를 사용하는 경우 디버그하기 어려운 문제를 경험할 수 있습니다.

나는 항상 와일드 카드를 사용하지 않습니다. 이렇게하면 열이 이름을 변경하면 즉시보기 또는 쿼리에 오류가 발생하고 어디에서 수정 해야하는지 알고 있습니다. 기본 테이블에서 열이 위치를 변경하면보기 또는 쿼리에서 열의 순서를 지정하면이를 보상합니다.

이러한 다른 대답은 모두 좋은 점을 가지고 있지만 SQL Server에는 적어도 몇 가지 잘못된 점이 있습니다. 이 시도:

create table temp (i int, j int)
go
create view vtemp as select * from temp
go
insert temp select 1, 1
go
alter table temp add k int
go
insert temp select 1, 1, 1
go
select * from vtemp

SQL Server는 추가 될 때 "새"열에 대해 배우지 않습니다. 당신이 원하는 것에 따라 이것이 좋은 일이거나 나쁜 일이 될 수 있지만, 어느 쪽이든 그것에 의존하는 것은 좋지 않을 것입니다. 따라서 피하는 것은 좋은 생각처럼 보입니다.

나 에게이 이상한 행동은 선택 *을 피해야하는 가장 강력한 이유입니다.

이 의견은 MySQL이 비슷한 동작을 가지고 있으며 Oracle은 그렇지 않다고 가르쳐주었습니다 (테이블 변경에 대해 배울 것입니다). 나에게 이러한 불일치는 Select *를 사용하지 않는 더 많은 이유입니다.

생산에 '*'를 사용하는 것은 나쁜 일입니다. 일회성 쿼리에 적합하지만 프로덕션 코드에서는 항상 가능한 한 명시 적이어야합니다.

특히 뷰의 경우, 기본 테이블에 열이 추가되거나 제거 된 경우, 뷰가 다시 컴파일 될 때까지 뷰가 잘못되거나 파손됩니다.

사용 SELECT * 뷰 내에서 열이보기 외부에서 사용되지 않으면 뷰 내에서 성능 오버 헤드가 많이 발생하지 않습니다. Optimizer는이를 최적화합니다. SELECT * FROM TheView 네트워크 연결에서 더 많은 열을 가져올 때와 마찬가지로 대역폭을 낭비 할 수 있습니다.

실제로, 나는 Datawarehouse의 여러 거대한 테이블에서 거의 모든 열을 연결하는 뷰가 성능 문제를 전혀 도입하지 않았으며, 비교적 소수의 열을 통해서도 시야 외부에서 요청됩니다. Optimizer는이를 잘 처리하고 외부 필터 기준을 매우 잘 견딜 수 있습니다.

그러나 위에서 주어진 모든 이유에 대해서는 거의 사용하지 않습니다. SELECT *.

여러 CTE가 서로 위에 구축되는 비즈니스 프로세스가 있으며, 파생 된 열에서 파생 된 열에서 파생 된 열을 효과적으로 구축합니다 (비즈니스가 이러한 계산을 합리화하고 단순화함에 따라 언젠가는 리플렉스되기를 바랍니다). , 나는 매번 멈출 수있는 모든 열이 필요하며 사용합니다. SELECT * - 하지만 SELECT * 베이스 층에서는 첫 번째 CTE와 마지막 CTE 사이에만 사용되지 않습니다.

SQL Server의 상황은 실제로 @user12861의 답변보다 훨씬 나쁩니다. SELECT * 여러 테이블에 대해 쿼리 초기에 참조 된 테이블에 열을 추가하면 실제로보기가 오래된 열의 모습으로 새 열의 값을 반환합니다. 아래 예를 참조하십시오.

-- create two tables
CREATE TABLE temp1 (ColumnA INT, ColumnB DATE, ColumnC DECIMAL(2,1))
CREATE TABLE temp2 (ColumnX INT, ColumnY DATE, ColumnZ DECIMAL(2,1))
GO


-- populate with dummy data
INSERT INTO temp1 (ColumnA, ColumnB, ColumnC) VALUES (1, '1/1/1900', 0.5)
INSERT INTO temp2 (ColumnX, ColumnY, ColumnZ) VALUES (1, '1/1/1900', 0.5)
GO


-- create a view with a pair of SELECT * statements
CREATE VIEW vwtemp AS 
SELECT *
FROM temp1 INNER JOIN temp2 ON 1=1
GO


-- SELECT showing the columns properly assigned
SELECT * FROM vwTemp 
GO


-- add a few columns to the first table referenced in the SELECT 
ALTER TABLE temp1 ADD ColumnD varchar(1)
ALTER TABLE temp1 ADD ColumnE varchar(1)
ALTER TABLE temp1 ADD ColumnF varchar(1)
GO


-- populate those columns with dummy data
UPDATE temp1 SET ColumnD = 'D', ColumnE = 'E', ColumnF = 'F'
GO


-- notice that the original columns have the wrong data in them now, causing any datatype-specific queries (e.g., arithmetic, dateadd, etc.) to fail
SELECT *
FROM vwtemp
GO

-- clean up
DROP VIEW vwTemp
DROP TABLE temp2
DROP TABLE temp1

항상 모든 변수가 필요하지는 않으며 구체적으로 필요한 것에 대해 생각하고 있는지 확인하기 때문입니다.

예를 들어 사이트에 사용자 목록을 작성할 때 데이터베이스에서 모든 해시 비밀번호를 가져 오는 점이 없으므로 Select *는 비생산적입니다.

옛날 옛적에, 나는 다른 데이터베이스 (동일한 서버)에서 테이블에 대한보기를 만들었습니다.

Select * From dbname..tablename

그런 다음 어느 날, 열이 타겟팅 된 테이블에 추가되었습니다. 보기가 재배치 될 때까지 완전히 잘못된 결과를 반환하기 시작했습니다.


완전히 틀렸다 : 줄 없음.

이것은 SQL Server 2000에있었습니다.

나는 이것이 내가 사용하더라도보기가 캡처 한 syscolumns 값 때문이라고 추측합니다.

SQL 쿼리는 기본적으로 프로그래머가 일부 컨텍스트에서 사용하기 위해 설계한 기능 단위입니다.장기적인 안정성과 지원 가능성(귀하가 아닌 다른 사람에 의해 가능)을 위해 기능 단위의 모든 것은 목적을 위해 존재해야 하며, 그것이 존재하는 이유, 특히 데이터의 모든 요소가 합리적으로 분명(또는 문서화)되어야 합니다.

지금부터 2년 후에 귀하의 쿼리를 변경해야 하거나 변경하려는 욕구가 생긴다면, 나는 그것을 엉망으로 만들 수 있다는 확신을 갖기 전에 꽤 철저하게 조사할 것으로 기대합니다.이는 모든 열이 호출되는 이유를 이해해야 함을 의미합니다.(둘 이상의 컨텍스트에서 쿼리를 재사용하려는 경우 이는 더욱 분명하게 사실입니다.비슷한 이유로 일반적으로 문제가 있습니다.) 출력에서 ​​어떤 목적과 관련이 없는 열을 본다면 그 내용과 이유를 이해하지 못했을 것입니다. 그것을 바꾸면 어떤 결과가 나올지.

일반적으로 사용하는 것은 나쁜 생각입니다 *. 일부 코드 인증 엔진은 이것을 경고로 표시하고 필요한 열만 명시 적으로 참조하도록 조언합니다. *를 사용하면 모든 열만 필요하지 않기 때문에 성능 사탕무로 이어질 수 있습니다. 그러나 반면에 * 사용이 이상적인 경우가 있습니다. 제공 한 예제를 사용하든이보기 (aview)를 위해이 테이블의 모든 열이 항상 필요하다고 상상해보십시오. 앞으로 열이 추가되면보기를 변경할 필요가 없습니다. 이것은 당신이 다루는 사건에 따라 좋거나 나쁠 수 있습니다.

나는 그것이 당신이 사용하는 언어에 달려 있다고 생각합니다. 언어 또는 DB 드라이버가 결과의 DICT (Python, Perl 등) 또는 연관 배열 (PHP)을 반환 할 때 Select *를 사용하는 것이 좋습니다. 배열의 색인이 아닌 이름으로 열을 언급하는 경우 코드를 쉽게 이해할 수 있습니다.

다른 사람은 그것을 언급 한 것 같지만 SQL Server 내에서는 스키 메이드 기인하다.

이는 뷰 정의에 영향을 미치는 기본 테이블 (삭제 포함)에 대한 수정을 방지합니다.

이것은 어떤 상황에서 당신에게 유용 할 수 있습니다. 나는 당신의 질문에 정확히 대답하지 않았다는 것을 알고 있지만 그럼에도 불구하고 강조 할 것이라고 생각했습니다.

Select *를 사용하여 조인이있는 경우 자동으로 조인 필드의 데이터가 반복 될 때 필요한 것보다 더 많은 데이터를 반환한다는 것을 의미합니다. 이것은 데이터베이스 및 네트워크 리소스의 낭비입니다.

다른 뷰를 호출하는 뷰를 사용하기에 충분히 순진한 경우, Select *를 사용하여 더 나쁜 성능을 제공 할 수 있습니다 (이것은 자체적으로 성능에 좋지 않은 기술입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top