태그 보관물: database

database

SELECT *가 왜 유해한 것으로 간주됩니까?

SELECT *나쁜 습관이 있습니까? 원하는 새 열을 추가하면 변경하는 코드가 적지 않습니까?

SELECT COUNT(*)일부 DB의 성능 문제 라는 것을 알고 있지만 실제로 모든 열을 원한다면 어떻게해야합니까?



답변

실제로 세 가지 주요 이유가 있습니다.

  • 소비자에게 데이터를 옮기는 데 비효율적입니다. SELECT *를 선택하면 응용 프로그램이 실제로 작동 해야하는 것보다 데이터베이스에서 더 많은 열을 검색하는 경우가 많습니다. 이로 인해 더 많은 데이터가 데이터베이스 서버에서 클라이언트로 이동하여 액세스 속도가 느려지고 시스템의로드가 증가하며 네트워크를 통해 이동하는 데 더 많은 시간이 소요됩니다. 이것은 존재하지 않았고 원래 소비자가 데이터 액세스를 코딩 할 때 필요하지 않은 기본 테이블에 새 열을 추가 할 때 특히 그렇습니다.

  • 인덱싱 문제 쿼리를 높은 수준의 성능으로 조정하려는 시나리오를 고려하십시오. *를 사용하고 실제로 필요한 것보다 많은 열을 반환하는 경우 서버는 종종 다른 방법보다 데이터를 검색하는 데 더 비싼 방법을 수행해야합니다. 예를 들어, SELECT 목록의 열을 포괄하는 인덱스를 만들 수 없으며, (모든 열 [ shudder ]를 포함하여 ), 주변에 와서 열을 추가 한 다음 사람을 포함하더라도 표를 사용하면 최적화 도구가 최적화 된 커버리지 색인을 무시하게되므로 쿼리 성능이 명백한 이유없이 크게 떨어질 수 있습니다.

  • 바인딩 문제. SELECT *를 선택하면 서로 다른 두 테이블에서 같은 이름의 두 열을 검색 할 수 있습니다. 이것은 종종 데이터 소비자를 망칠 수 있습니다. 두 테이블에 “ID”라는 열이있는 두 개의 테이블을 조인하는 쿼리를 상상해보십시오. 소비자는 어느 것이 어느 것인지 어떻게 알 수 있습니까? SELECT *는 기본 테이블 구조가 변경 될 때 뷰 (적어도 일부 버전에서는 SQL Server)를 혼동 할 수 있습니다 . 뷰가 다시 작성되지 않고 다시 오는 데이터가 넌센스 일 수 있습니다 . 그리고 최악의 부분은 원하는대로 열 이름을 지정할 수 있지만 다음에 오는 사람은 이미 개발 한 열과 충돌 할 열을 추가하는 것에 대해 걱정할 필요가 없다는 것입니다. 이름.

그러나 SELECT *에 모두 나쁜 것은 아닙니다. 나는이 사용 사례에 그것을 자유롭게 사용합니다.

  • 임시 쿼리. 특히 익숙하지 않은 좁은 테이블에서 무언가를 디버깅하려고 할 때 SELECT *가 종종 내 가장 친한 친구입니다. 기본 열 이름이 무엇인지에 대한 연구를 수행하지 않고도 진행중인 일을 볼 수 있습니다. 이것은 열 이름이 길수록 더 큰 “플러스”가됩니다.

  • *가 “행”을 의미 할 때. 다음 유스 케이스에서 SELECT *는 괜찮으며 성능 킬러라는 소문은 수년 전에 일부 유효성이 있었지만 현재는 그렇지 않은 도시 전설 일뿐입니다.

    SELECT COUNT(*) FROM table;

    이 경우 *는 “행 수 계산”을 의미합니다. * 대신 열 이름을 사용하는 경우 해당 열의 값이 null이 아닌 행을 계산합니다 . COUNT (*)는 실제로 수를 세는 개념을 고수하고 집계에서 NULL이 제거되어 발생하는 이상한 대소 문자를 피합니다.

    이 유형의 쿼리도 마찬가지입니다.

    SELECT a.ID FROM TableA a
    WHERE EXISTS (
        SELECT *
        FROM TableB b
        WHERE b.ID = a.B_ID);

    소금의 가치가있는 모든 데이터베이스에서 *는 “행”을 의미합니다. 하위 쿼리에 넣은 내용은 중요하지 않습니다. 일부 사람들은 SELECT 목록에서 b의 ID를 사용하거나 숫자 1을 사용하지만 IMO는 그 관례가 거의 의미가 없습니다. 당신이 의미하는 것은 “행 수를 세는 것”이며, 그것이 *를 의미하는 것입니다. 대부분의 쿼리 최적화 프로그램은이를 알기에 충분히 똑똑합니다. (솔직히 말해서, 나는 이것이 SQL Server와 Oracle 에서만 사실이라는 것을 알고 있습니다.)


답변

SELECT 문에서 별표 문자 “*”는 쿼리와 관련된 테이블의 모든 열에 대한 축약 형입니다.

공연

*속기이 될 수 느린 이유는

  • 모든 필드가 색인화되는 것은 아니므로 전체 테이블 스캔이 필요합니다. 효율성은 떨어집니다.
  • SELECT *와이어 로 전송하기 위해 저장 한 항목으로 전체 테이블 스캔 위험
  • 필요한 것보다 더 많은 데이터 반환
  • 가변 길이 데이터 유형을 사용하여 후행 열을 리턴하면 검색 오버 헤드가 발생할 수 있습니다.

유지

사용시 SELECT *:

  • 코드베이스에 익숙하지 않은 사람은 문서를 참조하여 유능한 변경을 수행하기 전에 어떤 열이 반환되는지 알고 있어야합니다. 코드를 더 읽기 쉽게 만들고 코드에 익숙하지 않은 사람들에게 필요한 모호함과 작업을 최소화하면 장기적으로 더 많은 시간과 노력을 절약 할 수 있습니다.
  • 코드가 열 순서에 의존하는 SELECT *경우 테이블의 열 순서가 변경된 경우 발생하는 오류를 숨 깁니다.
  • 쿼리가 작성 될 때 모든 열이 필요하더라도 앞으로는 그렇지 않을 수 있습니다
  • 사용법이 프로파일 링을 복잡하게한다

디자인

SELECT *입니다 안티 패턴 :

  • 쿼리의 목적은 덜 분명합니다. 응용 프로그램에서 사용하는 열이 불투명합니다
  • 가능할 때마다 엄격한 타이핑을 사용하는 것에 대한 모듈성 규칙을 위반합니다. 명시 적으로 거의 보편적으로 좋습니다.

“SELECT *”는 언제 사용해야합니까?

그것은 사용하는 것이 허용의 SELECT *쿼리가 작성 될 때 존재하는 모든 열 반대로 테이블 (들)의 모든 컬럼에 대한 명시 적 필요성 참여가있을 때. 데이터베이스는 *를 전체 열 목록으로 내부적으로 확장하므로 성능 차이는 없습니다.

그렇지 않으면 테이블 별칭을 사용하는 동안 쿼리에 사용될 모든 열을 명시 적으로 나열하십시오.


답변

지금 모든 열을 선택하려는 경우에도 누군가 하나 이상의 새 열을 추가 한 후 모든 열을 선택하지 않을 수 있습니다. 쿼리를 작성하면 SELECT *어떤 시점에서 누군가 텍스트 열을 추가하여 실제로 해당 열이 필요하지 않더라도 쿼리 실행 속도가 느려질 위험이 있습니다.

원하는 새 열을 추가하면 변경하는 코드가 적지 않습니까?

실제로 새 열을 사용하려면 어쨌든 코드를 상당히 많이 변경해야 할 가능성이 있습니다. , new_column입력하는 것만으로 저장 만 됩니다.


답변

SELECT 문의 열 이름을 지정하면 지정된 순서대로 열이 반환되므로 숫자 인덱스로 안전하게 참조 될 수 있습니다. “SELECT *”를 사용하면 임의의 순서로 열을 수신하게되므로 이름으로 만 열을 안전하게 사용할 수 있습니다. 데이터베이스에 추가되는 새 열로 수행 할 작업을 미리 알지 못하는 경우 가장 가능한 올바른 조치는 무시하는 것입니다. 데이터베이스에 추가되는 새 열을 무시하려는 경우 열을 검색해도 아무런 이점이 없습니다.


답변

많은 상황에서 SELECT *는 디자인 타임이 아닌 애플리케이션에서 런타임시 오류를 발생시킵니다. 열 변경에 대한 지식이나 응용 프로그램의 잘못된 참조를 숨 깁니다.


답변

모든 열을 정말로 원한다면 select (*)와 열 이름 지정 사이의 성능 차이를 보지 못했습니다. 열 이름을 지정하는 드라이버는 코드에서 어떤 열을 보게 될지 명시적일 수 있습니다.

그러나 모든 컬럼을 원하지는 않으며 select (*)로 인해 데이터베이스 서버에 불필요한 작업이 발생하고 불필요한 정보가 네트워크를 통해 전달되어야합니다. 시스템을 많이 사용하거나 네트워크 연결이 느린 경우가 아니면 눈에 띄는 문제가 발생하지 않습니다.


답변

앱과 데이터베이스 간의 연결을 줄이는 것으로 생각하십시오.

‘코드 냄새’측면을 요약하려면
SELECT *앱과 스키마 사이에 동적 종속성을 만듭니다. 사용을 제한하는 것은 종속성을보다 명확하게 정의하는 한 가지 방법입니다. 그렇지 않으면 데이터베이스를 변경하면 응용 프로그램이 충돌 할 가능성이 커집니다.