조인이 나쁘거나 '느린'이유는 무엇입니까? 나는 이것을 한 번 더 들었다는 것을 안다. 이 인용구를 찾았습니다
문제는 조인이 상대적으로 느리고 특히 매우 큰 데이터 세트에서 느리고 웹 사이트가 느리다는 것입니다. 디스크에서 분리 된 모든 정보를 가져 와서 모두 다시 모으려면 오랜 시간이 걸립니다.
나는 항상 그들이 특히 PK를 찾을 때 빠르다고 생각했습니다. 왜 '느리다'고?
조인이 나쁘거나 '느린'이유는 무엇입니까? 나는 이것을 한 번 더 들었다는 것을 안다. 이 인용구를 찾았습니다
문제는 조인이 상대적으로 느리고 특히 매우 큰 데이터 세트에서 느리고 웹 사이트가 느리다는 것입니다. 디스크에서 분리 된 모든 정보를 가져 와서 모두 다시 모으려면 오랜 시간이 걸립니다.
나는 항상 그들이 특히 PK를 찾을 때 빠르다고 생각했습니다. 왜 '느리다'고?
답변:
확장 성은 작업 단위당 리소스 사용을 최소화하기 위해 반복되는 작업을 사전 컴퓨팅, 분산 또는 기본 요소로 축소하는 것입니다. 확장을 잘하기 위해 필요하지 않은 작업을 수행하지 않고 실제로 수행하는 작업을 최대한 효율적으로 수행합니다.
물론 두 개의 개별 데이터 소스를 결합하는 것은 사용자가 요청하는 지점에서 라이브로 수행해야하는 작업이기 때문에 적어도 결합하지 않는 것에 비해 상대적으로 느립니다.
그러나 대안은 더 이상 두 개의 개별 데이터를 전혀 가지지 않는다는 것을 기억하십시오. 두 개의 서로 다른 데이터 포인트를 동일한 레코드에 넣어야합니다. 어딘가에 결과없이 두 개의 서로 다른 데이터를 결합 할 수 없으므로 장단점을 이해해야합니다.
좋은 소식은 현대의 관계형 데이터베이스가 조인에 능하다 는 것 입니다. 좋은 데이터베이스를 잘 사용하면 조인이 느리다고 생각해서는 안됩니다. 원시 조인을 가져와 훨씬 더 빠르게 만드는 확장 성 친화적 인 방법은 여러 가지가 있습니다 .
나는 지금까지 말을 갈 것 관계형 데이터베이스 모두에 존재하는 주된 이유는 당신이 할 수 있도록하는 것입니다 효율적으로 결합 * . 확실히 구조화 된 데이터를 저장하는 것만이 아닙니다 (csv 또는 xml과 같은 플랫 파일 구조를 사용하여 수행 할 수 있음). 내가 나열한 몇 가지 옵션을 사용하면 사전에 조인을 완전히 구축 할 수 있으므로 쿼리를 실행하기 전에 결과가 이미 완료되었습니다. 마치 데이터를 비정규 화 한 것처럼 (당연히 쓰기 작업 속도가 느려집니다).
조인이 느린 경우 데이터베이스를 올바르게 사용하고 있지 않을 수 있습니다.
비정규 화는 이러한 다른 기술이 실패한 후에 만 수행되어야합니다. "실패"를 진정으로 판단 할 수있는 유일한 방법은 의미있는 성능 목표를 설정하고 해당 목표에 대해 측정하는 것입니다. 측정하지 않았다면 비정규 화에 대해 생각조차하기에는 너무 이르다.
* 즉, 단순한 테이블 모음과는 다른 엔티티로 존재합니다. 실제 rdbms의 또 다른 이유는 안전한 동시 액세스입니다.
조인은 비정규 화를 통해 피하는 것보다 느릴 수 있지만 올바르게 사용하면 (적절한 인덱스가있는 열에 조인하는 등) 본질적으로 느리지 않습니다 .
비정규 화는 잘 설계된 데이터베이스 스키마가 성능 문제를 나타내는 경우 고려할 수있는 많은 최적화 기술 중 하나입니다.
기사에 따르면 조인이없는 경우에 비해 느립니다. 이것은 비정규 화로 달성 할 수 있습니다. 그래서 속도와 정규화 사이에는 상충 관계가 있습니다. 조기 최적화도 잊지 마세요 :)
우선, 관계형 데이터베이스의 존재 이유 (존재 이유)는 엔티티 간의 관계를 모델링 할 수 있다는 것입니다. 조인은 단순히 이러한 관계를 탐색하는 메커니즘입니다. 확실히 명목상의 비용이 들지만 조인이 없으면 관계형 데이터베이스를 가질 이유가 없습니다.
학문적 세계에서 우리는 다양한 정규형 (1st, 2nd, 3rd, Boyce-Codd 등)과 같은 것을 배우고 다양한 유형의 키 (기본, 외국, 대체, 고유 등) 및 방법을 배웁니다. 이러한 것들은 데이터베이스를 설계하는 데 적합합니다. 그리고 SQL의 기초를 배우고 구조와 데이터 (DDL 및 DML)를 조작합니다.
기업 세계에서 많은 학문적 구성은 우리가 믿었던 것보다 훨씬 덜 실행 가능하다는 것이 밝혀졌습니다. 완벽한 예는 기본 키의 개념입니다. 학문적으로는 테이블에서 한 행을 고유하게 식별하는 속성 (또는 속성 모음)입니다. 따라서 많은 문제 영역에서 적절한 학문적 기본 키는 3 개 또는 4 개의 속성의 조합입니다. 그러나 현대 기업 세계의 거의 모든 사람들은 자동 생성 된 순차적 정수를 테이블의 기본 키로 사용합니다. 왜? 두 가지 이유. 첫 번째는 FK를 사방으로 마이그레이션 할 때 모델을 훨씬 더 깔끔하게 만들기 때문입니다. 두 번째이며이 질문과 가장 밀접한 관계는 조인을 통해 데이터를 검색하는 것이 4 개의 varchar 열 (몇몇 사람들이 이미 언급했듯이)보다 단일 정수에서 더 빠르고 효율적이라는 것입니다.
이제 실제 데이터베이스의 두 가지 특정 하위 유형에 대해 좀 더 자세히 살펴 보겠습니다. 첫 번째 유형은 트랜잭션 데이터베이스입니다. 이는 최신 사이트를 구동하는 많은 전자 상거래 또는 콘텐츠 관리 응용 프로그램의 기반입니다. 트랜잭션 DB를 사용하면 "트랜잭션 처리량"에 대해 크게 최적화하고 있습니다. 대부분의 상거래 또는 콘텐츠 앱은 쿼리 성능 (특정 테이블의)과 삽입 성능 (다른 테이블의) 간의 균형을 맞춰야하지만, 각 앱에는 고유 한 비즈니스 중심 문제가 해결되어야합니다.
두 번째 유형의 실제 데이터베이스는보고 데이터베이스입니다. 이들은 거의 독점적으로 비즈니스 데이터를 집계하고 의미있는 비즈니스 보고서를 생성하는 데 사용됩니다. 일반적으로 데이터가 생성되는 트랜잭션 데이터베이스와 모양이 다르며 대량 데이터 세트 또는 복잡한 데이터 세트의 쿼리 성능과 대량 데이터로드 (ETL) 속도에 대해 고도로 최적화되어 있습니다.
각각의 경우 개발자 또는 DBA는 기능과 성능 곡선의 균형을 신중하게 조정해야하며, 방정식 양쪽에 많은 성능 향상 트릭이 있습니다. Oracle에서는 "계획 설명"을 수행 할 수 있으므로 쿼리가 구문 분석되고 실행되는 방식을 구체적으로 볼 수 있습니다. DB의 적절한 인덱스 사용을 극대화하려고합니다. 하나의 정말 불쾌한 금지는 쿼리의 where 절에 함수를 넣는 것입니다. 그렇게 할 때마다 Oracle이 해당 특정 열에 대한 인덱스를 사용하지 않도록 보장하고 Explain 플랜에서 전체 또는 부분 테이블 스캔을 볼 수 있습니다. 이것은 쿼리가 어떻게 작성 될 수 있는지에 대한 하나의 구체적인 예일 뿐이며 결과적으로 속도가 느려지고 조인과 관련이 없습니다.
테이블 스캔에 대해 이야기하는 동안 테이블 크기에 비례하여 쿼리 속도에 분명히 영향을 미칩니다. 100 개 행의 전체 테이블 스캔은 눈에 띄지 않습니다. 1 억 개의 행이있는 테이블에서 동일한 쿼리를 실행하면 다음 주에 반환해야합니다.
정규화에 대해 잠시 이야기 해 봅시다. 이것은 과도한 스트레스를받을 수있는 매우 긍정적 인 학문적 주제입니다. 정규화에 대해 이야기 할 때 대부분의 경우 중복 데이터를 자체 테이블에 넣고 FK를 마이그레이션하여 제거하는 것을 의미합니다. 사람들은 일반적으로 2NF와 3NF가 설명하는 전체 의존성 문제를 건너 뜁니다. 그러나 극단적 인 경우에는 정규화 되었기 때문에 코드를 작성할 수있는 거대하고 완전한 짐승 인 완벽한 BCNF 데이터베이스를 보유 할 수 있습니다.
그래서 우리는 어디에서 균형을 잡을까요? 하나의 베스트 답변은 없습니다. 모든 더 나은 대답은 구조 유지 관리의 용이성, 데이터 유지 관리의 용이성 및 코드 생성 / 유지 관리의 용이성 사이의 타협 인 경향이 있습니다. 일반적으로 데이터 중복이 적을수록 좋습니다.
그렇다면 조인이 때때로 느린 이유는 무엇입니까? 때로는 잘못된 관계형 디자인입니다. 때로는 비효율적 인 인덱싱입니다. 때로는 데이터 볼륨 문제입니다. 때로는 끔찍하게 작성된 쿼리입니다.
그렇게 긴 답변을 드려서 미안하지만, 4 개의 글 머리 기호로 답하는 것보다 내 댓글에 대해 더 자세한 맥락을 제공해야한다는 느낌이 들었습니다.
테라 바이트 크기의 데이터베이스를 사용하는 사람들은 여전히 조인을 사용합니다. 성능 측면에서 작업 할 수 있다면 조인을 사용할 수 있습니다.
denomalize하지 않는 데는 여러 가지 이유가 있습니다. 첫째, 선택 쿼리의 속도는 데이터베이스의 유일한 또는 주요 관심사가 아닙니다. 데이터의 무결성이 첫 번째 관심사입니다. 비정규 화하는 경우 상위 데이터가 변경 될 때 데이터를 비정규 화 상태로 유지하는 기술을 적용해야합니다. 따라서 client_Id의 클라이언트 테이블에 조인하는 대신 모든 테이블에 클라이언트 이름을 저장한다고 가정합니다. 이제 클라이언트 이름이 변경되면 (시간이 지남에 따라 일부 클라이언트 이름이 변경 될 확률이 100 %) 이제 해당 변경 사항을 반영하도록 모든 하위 레코드를 업데이트해야합니다. 이 작업을 수행하면 계단식 업데이트가 수행되고 백만 개의 하위 레코드가있는 경우 얼마나 빠르며 잠금 문제가 발생하고 작업이 지연되는 동안 얼마나 많은 사용자가 작업 지연을 겪을 것이라고 생각하십니까? 비정규 화하는 대부분의 사람들은 "
비정규 화는 올바르게 수행하려면 데이터베이스 성능 및 무결성에 대한 철저한 이해가 필요한 복잡한 프로세스입니다. 직원에 대한 전문 지식이없는 한 비정규 화를 시도하지 마십시오.
조인은 몇 가지 작업을 수행하면 충분히 빠릅니다. 먼저 suggorgate 키를 사용하면 int 조인이 거의 가장 빠른 조인입니다. 두 번째는 항상 외래 키를 인덱싱합니다. 파생 테이블 또는 조인 조건을 사용하여 필터링 할 더 작은 데이터 집합을 만듭니다. 매우 복잡한 대규모 데이터베이스가있는 경우 대규모 데이터베이스 분할 및 관리 경험이있는 전문 데이터베이스 담당자를 고용하십시오. 조인을 제거하지 않고 성능을 향상시킬 수있는 많은 기술이 있습니다.
쿼리 기능 만 필요하면 비정규 화 될 수 있고 사용자 데이터 입력이 아닌 ETL 도구 (속도 최적화)를 통해 채워지는 데이터웨어 하우스를 설계 할 수 있습니다.
각 측면에서 많은 레코드 부분을 스캔해야하는 경우 조인 속도가 느려질 수 있습니다.
이렇게 :
SELECT SUM(transaction)
FROM customers
JOIN accounts
ON account_customer = customer_id
인덱스가에 정의되어 있어도 account_customer
후자의 모든 레코드를 스캔해야합니다.
쿼리 목록의 경우 괜찮은 최적화 프로그램은 인덱스 액세스 경로를 고려하지 않고 대신 a HASH JOIN
또는 a MERGE JOIN
를 수행합니다 .
다음과 같은 쿼리의 경우 :
SELECT SUM(transaction)
FROM customers
JOIN accounts
ON account_customer = customer_id
WHERE customer_last_name = 'Stellphlug'
조인은 가장 빠를 것입니다. 먼저 customer_last_name
모든 Stellphlug (물론 많지는 않지만)를 필터링하는 데 인덱스 가 사용 된 다음 account_customer
각 Stellphlug 에 대한 인덱스 스캔 이 실행되어 트랜잭션을 찾습니다.
accounts
및 에서 수십억 개의 레코드가 될 수 있다는 사실에도 불구하고 실제로 customers
스캔해야하는 레코드는 거의 없습니다.
accounts(account_customer)
대부분의 RDBMS 에 정의 된 경우 해당 인덱스를 사용하여 customers
데이터베이스 의 어떤 행을 스캔 해야하는지 정확히 알아냅니다 .
HASH JOIN
는 훨씬 빠르기 때문에를 제외한 모든 주요 데이터베이스에서 사용되는 것입니다 MySQL
. 이는 customers
중첩 루프에서 선두를 만들 것입니다 (크기가 더 작기 때문에)
Joins are fast.
조인은 적절하게 정규화 된 데이터베이스 스키마를 사용하는 표준 방식으로 간주되어야합니다. 조인을 사용하면 서로 다른 데이터 그룹을 의미있는 방식으로 조인 할 수 있습니다. 가입을 두려워하지 마십시오.
주의 할 점은 정규화, 조인 및 인덱스의 적절한 사용을 이해해야한다는 것입니다.
모든 개발 프로젝트 중 가장 실패한 것이 기한을 맞추고 있으므로 조기 최적화에주의하십시오. 프로젝트를 완료하고 장단점을 이해하면 정당화 할 수 있다면 규칙을 위반할 수 있습니다.
데이터 세트의 크기가 증가함에 따라 조인 성능이 비선형 적으로 저하되는 것은 사실입니다. 따라서 단일 테이블 쿼리만큼 잘 확장되지는 않지만 여전히 확장됩니다.
새가 날개없이 더 빨리 날아가지만 똑바로 내려가는 것도 사실입니다.
조인은 데이터를 "조인"하기 위해 더 많은 파일과 더 많은 인덱스를 검색해야하므로 추가 처리가 필요합니다. 그러나 "매우 큰 데이터 세트"는 모두 상대적입니다. large 정의 나는 JOIN의 경우 전체 데이터 세트가 아닌 큰 결과 세트에 대한 참조라고 생각합니다.
대부분의 데이터베이스는 기본 테이블에서 5 개의 레코드를 선택하고 각 레코드에 대해 관련 테이블의 5 개 레코드를 조인하는 쿼리를 매우 빠르게 처리 할 수 있습니다 (올바른 인덱스가 제자리에 있다고 가정). 이러한 테이블에는 각각 수억 개 또는 수십억 개의 레코드가있을 수 있습니다.
결과 세트가 증가하기 시작하면 상황이 느려질 것입니다. 동일한 예를 사용하여 기본 테이블의 결과가 10 만 개의 레코드 인 경우 검색해야하는 "조인 된"레코드가 50 만 개가됩니다. 추가 지연으로 데이터베이스에서 그만큼 많은 데이터를 가져옵니다.
JOIN을 피하지 마세요. 데이터 세트가 "매우 커지면"최적화 / 비정규 화해야 할 수도 있다는 점만 알아 두세요.
또한 당신이 인용 한 기사에서 :
수십억 개의 레코드, 페타 바이트의 데이터, 수천 명의 동시 사용자 및 하루에 수백만 개의 쿼리가 수행되는 많은 메가 스케일 웹 사이트는 샤딩 체계를 사용하고 있으며 일부는 데이터 계층을 설계하기위한 최상의 전략으로 비정규 화를 옹호하기도합니다.
과
그리고 당신이 정말로 큰 웹 사이트가 아니라면 아마도이 정도의 복잡성에 대해 걱정할 필요가 없을 것입니다.
과
데이터베이스가이 모든 작업을 수행하도록하는 것보다 오류가 발생하기 쉽지만 최고급 데이터베이스도 처리 할 수있는 것 이상으로 확장 할 수 있습니다.
이 기사는 Ebay와 같은 메가 사이트에 대해 논의하고 있습니다. 이 수준의 사용에서는 일반 바닐라 관계형 데이터베이스 관리 이외의 다른 것을 고려해야 할 것입니다. 그러나 "정상적인"비즈니스 과정 (수천 명의 사용자와 수백만 개의 레코드가있는 애플리케이션)에서는 더 비싸고 오류가 발생하기 쉬운 접근 방식이 과도합니다.
적절한 인덱스와 올바르게 작성된 쿼리를 포함하는 올바르게 설계된 테이블은 항상 느리지는 않습니다. 당신이 그것을 들었던 곳 :
조인이 나쁘거나 '느린'이유
그들이 무슨 말을하는지 전혀 모른다 !!! 대부분의 조인은 매우 빠릅니다. 한 번에 많은 행을 조인해야하는 경우 비정규 화 된 테이블에 비해 적중을받을 수 있지만 제대로 설계된 테이블로 돌아가서 비정규 화 시점과 비정규 화 시점을 알 수 있습니다. 무거운보고 시스템에서는 보고서를 위해 비정규 화 된 테이블에서 데이터를 분리하거나 데이터웨어 하우스를 만들 수도 있습니다. 트랜잭션이 많은 시스템에서는 테이블을 정규화합니다.
생성되는 임시 데이터의 양은 조인에 따라 엄청날 수 있습니다.
예를 들어, 여기 직장에서 한 데이터베이스에는 모든 필드가 선택 사항 인 일반 검색 기능이 있습니다. 검색 루틴은 검색이 시작되기 전에 모든 테이블에서 조인을 수행했습니다. 이것은 처음에는 잘 작동했습니다. 하지만 이제 기본 테이블에 천만 개가 넘는 행이 있습니다. 이제 검색하는 데 30 분 이상 걸립니다.
검색 저장 프로 시저를 최적화하는 일을 맡았습니다.
내가 한 첫 번째 작업은 메인 테이블의 필드가 검색되는 경우 해당 필드에서만 임시 테이블을 선택하는 것입니다. 그런 다음 나머지 검색을 수행하기 전에 모든 테이블을 해당 임시 테이블과 조인했습니다. 이제 기본 테이블 필드 중 하나가 10 초 미만으로 걸리는 곳을 검색합니다.
기본 테이블 필드가 검색을 시작하지 않으면 다른 테이블에 대해서도 유사한 최적화를 수행합니다. 내가 끝났을 때 검색은 대부분 10 초 미만으로 30 초 이상 걸리지 않습니다.
SQL 서버의 CPU 사용률도 감소했습니다.
조인 (아마도 정규화 된 디자인으로 인해)은 단일 테이블에서 읽는 것보다 데이터 검색 속도가 분명히 느릴 수 있지만, 전체 트랜잭션의 풋 프린트가 최소화되지 않기 때문에 비정규 화 된 데이터베이스는 데이터 생성 / 업데이트 작업에 느릴 수 있습니다.
정규화 된 데이터베이스에서는 데이터 조각이 한 곳에만 존재하므로 업데이트를위한 공간이 가능한 최소화됩니다. 비정규 화 된 데이터베이스에서는 여러 행 또는 여러 테이블의 동일한 열을 업데이트해야 할 수 있습니다. 즉, 풋 프린트가 더 커지고 잠금 및 교착 상태가 발생할 가능성이 높아질 수 있습니다.
예, 하나의 비정규 화 된 테이블에서 행을 선택하는 것이 (쿼리에 적합한 인덱스라고 가정) 여러 테이블을 조인하여 구성된 행을 선택하는 것보다 빠를 수 있습니다. 특히 조인에 사용 가능한 효율적인 인덱스가없는 경우 더욱 그렇습니다.
기사에 인용 된 예 (Flickr 및 eBay)는 예외적 인 경우 IMO이므로 예외적 인 응답을받을 자격이 있습니다. 저자는 특히 기사에서 RI의 부족과 데이터 중복의 정도를 언급합니다.
대부분의 애플리케이션 (다시 말하면 IMO)은 RDBMS가 제공하는 유효성 검사 및 중복 감소의 이점을 누립니다.