외래 키는 쿼리 성능을 향상 시킵니까?


149

제품 및 제품 범주에 2 개의 테이블이 있다고 가정합니다. 두 테이블 모두 CategoryId에 관계가 있습니다. 그리고 이것은 쿼리입니다.

SELECT p.ProductId, p.Name, c.CategoryId, c.Name AS Category
FROM Products p
INNER JOIN ProductCategories c ON p.CategoryId = c.CategoryId
WHERE c.CategoryId = 1;

실행 계획을 만들 때 Product Categories 테이블은 예상대로 클러스터 인덱스 검색을 수행합니다. 그러나 테이블 제품의 경우 클러스터 인덱스 스캔을 수행하므로 의심의 여지가 있습니다. FK가 쿼리 성능 향상에 도움이되지 않는 이유는 무엇입니까?

따라서 Products.CategoryId에 인덱스를 만들어야합니다. 실행 계획을 다시 만들면 두 테이블 모두 인덱스 검색을 수행합니다. 그리고 예상되는 서브 트리 비용이 많이 줄어 듭니다.

내 질문은 :

  1. FK 외에도 관계 제한에 도움이되지만 다른 유용성이 있습니까? 쿼리 성능이 향상됩니까?

  2. 모든 테이블의 모든 FK 열 (예 : Products.CategoryId)에 인덱스를 만들어야합니까?

답변:


186

외래 키는 성능 도구가 아닌 참조 무결성 도구입니다. 적어도 SQL Server에서 FK를 만들면 연결된 인덱스가 만들어지지 않으며 조회 시간을 향상시키기 위해 모든 FK 필드에 인덱스를 만들어야합니다.


40
좋은 모델은 (일반적으로) 더 잘 작동합니다.
Kenny Evitt

10
"외국 키는 관계형 무결성 도구"입니다. '관계형'이라는 단어를주의해서 사용하십시오. 외래 키는 데이터베이스 개념으로, 참조 무결성 제약 조건의 약자입니다. 그것들은 관계형 모델의 일부가 아닙니다. 오타가 있다고 가정합니다.
언젠가

7
@Kenny 종종 그렇습니다. 그러나 때로는 더 좋은 모델이 더 비쌉니다. 적절한 예 : 외래 키로 인해 더 많은 처리가 발생합니다.
Hans

8
외래 키 적어도 MySQL에서 성능을 향상시킵니다. 또한 FK를 만들면 인덱스가 만들어지지 않습니다. FK를 만들 려면 색인이 필요 합니다
Félix Gagnon-Grenier

15
이 답변은 질문에 대답하지 않기 때문에 거의 쓸모가 없습니다. 외래 키는 성능에 (긍정적) 영향을 미치지 는 않지만 의도 는 아닌 실제에 관한 문제였습니다.
John

58

외래 키는 성능을 향상시키고 상처를 줄 수 있습니다

  1. 여기에 언급 된 바와 같이 : 외래 키는 성능 향상

  2. 조회를 줄이려면 항상 FK 열에 색인을 작성해야합니다. SQL Server는이를 자동으로 수행하지 않습니다.

편집하다

이제 링크가 작동하지 않는 것처럼 보이 므로 (크리스마스에게 알려야 함) 다음은 외래 키가 성능을 향상시키고 손상시킬 수있는 이유를 보여줍니다.

외래 키로 성능 향상 가능

외래 키 제약 조건은 데이터를 읽을 때 성능을 향상시키는 동시에 데이터를 삽입 / 수정 / 삭제할 때 성능을 저하시킵니다.

쿼리를 읽는 경우 최적화 프로그램은 외래 키 제약 조건이 미리 선언 된 규칙이므로 외래 키 제약 조건을 사용하여보다 효율적인 쿼리 계획을 만들 수 있습니다. 예를 들어 옵티마이 저가 외래 키 제약 조건으로 인해 계획의 특정 부분을 실행할 필요가 없다는 것을 알 수 있기 때문에 일반적으로 쿼리 계획의 일부를 건너 뜁니다.


3
다음은 성능을 저하시킬 수있는 방법을 자세히 설명하는 링크입니다. devx.com/getHelpOn/10MinuteSolution/16595/0/page/2
cmsjr

3
말이 되겠지만 대량의 delete 문으로 만 실행됩니다. 아마도 OLAP 환경에서 인덱싱되지 않은 FK는 성능을 향상시키는 반면 OLTP 환경에서는 성능을 저하시킬 수 있습니다.
Lieven Keersmaekers

1
이 답변의 링크가 작동하지 않습니다. FK가 성능을 향상시키는 유일한 주장이기 때문에 불행한 일입니다.
Chris Moschini

1
@ChrisMoschini-지금까지 귀하의 의견을 알지 못했습니다. 당신이 언급했듯이, 링크는 죽었지 만 그것의 요지는 내가 게시 한 새로운 링크 (세부 사항과 함께)에 언급되어 있습니다.
Lieven Keersmaekers

2
승리를위한 Wayback Machine 링크 ! 이 기사는 SQLMag.com에서도 볼 수 있습니다 .
John Eisbrener

15

외래 키는 데이터베이스 무결성을 보장하기위한 DBMS 개념입니다.

모든 성능 관련 / 개선 사항은 사용중인 데이터베이스 기술에 따라 다르며 외래 키의 목적에 부차적입니다.

SQL Server에서는 모든 외래 키에 클러스터되지 않은 인덱스가 적어도 있는지 확인하는 것이 좋습니다.

이 문제가 해결되기를 바랍니다. 자세한 내용은 언제든지 문의하십시오.


9
@Kenny Evitt 무결성이 없으면 데이터가 쓸모가 없습니다. 나는 그것을 매우 쉽게 판매합니다.
HLGEM

@HLGEM 가끔씩 404 오류가 발생 하는 것은 여전히 ​​견딜 수 있습니다. 저렴한 리소스와 덜 복잡한 시스템을 사용하여 대가로 뛰어난 처리량을 달성함으로써 이제는 매우 쉽게 판매됩니다. 당신은 CAP 정리에 관심이있을 것 입니다.
Daniel Dinnyes

8
@Daniel Dinnyes, 데이터 무결성은 404 오류가 아닙니다. 유용한 데이터를 얻는 것입니다. 예를 들어 개발자의 무능력으로 인해 보고서의 주문 및 재무 데이터가 손실되지 않습니다. 외래 키를 사용하지 않는 것에 대한 변명은 없습니다.
HLGEM

2
HLGEM에 동의합니다. 코드가 무결성을 처리하도록하는 것이 항상 좋은 생각은 아닙니다. 데이터는 종종 의사 결정에 사용되지만 데이터가 손상되면 의사 결정이 정확하지 않습니다.
lepe

1
"외국 키는 관계형 무결성 도구"입니다. '관계형'이라는 단어를주의해서 사용하십시오. 외래 키는 데이터베이스 개념으로, 참조 무결성 제약 조건의 약자입니다. 그것들은 관계형 모델의 일부가 아닙니다. 오타가 있다고 가정합니다.
1

4

가장 좋은 방법은 자주 사용하는 필드에서 색인을 사용하는 것입니다. SQL Server를 사용하는 경우 프로파일 러를 사용하여 특정 데이터베이스를 프로파일 링하고 출력하는 파일을 가져오고 튜닝 마법사를 사용하여 인덱스를 배치 할 위치에 대한 권장 사항을받을 수 있습니다. 또한 프로파일 러를 사용하여 장기 실행 저장 프로 시저를 플러시하는 것을 좋아합니다. 매주 게시하는 10 가지 최악의 범죄자 목록이 있습니다.


3

쿼리를보다 효율적으로 만드는 데 사용할 수 있습니다. SQL Server에서 쿼리를 재구성하여 내부 조인 대신 외부 조인을 사용하여 SQL 서버에서 열에 null이 있는지 확인해야하는 필요성을 제거 할 수 있습니다. 외래 키 관계에 의해 이미 자격이 부여되므로 한정자를 넣을 필요가 없습니다.

그래서 이거:

    select p.ProductId, p.Name, c.CategoryId, c.Name AS Category 
from Products p inner join ProductCategories c on p.CategoryId = c.CategoryIdwhere c.CategoryId = 1;

이것이된다 :

SELECT p.ProductId, p.Name, c.CategoryId, c.Name AS Category 
FROM ProductCategories c 
LEFT OUTER JOIN Products P ON
c.CategoryId = p.CategoryId 
WHERE c.CategoryId = 1;

작은 쿼리에서 반드시 큰 성능을 발휘할 필요는 없지만 테이블이 커지면 더 효율적일 수 있습니다.


3
외부 조인은 일반적으로 내부 조인 ( stackoverflow.com/a/2726683/155892 ) 보다 효율성이 떨어질 뿐만 아니라 쿼리가 오도되기 쉽습니다. 그냥 명시 적으로하는 대신
Mark Sowul

2

MySQL 5.7의 경우 여러 조인과 관련된 쿼리 속도를 확실히 향상시킬 수 있습니다!

쿼리를 이해하기 위해 'explain'을 사용했으며 키가 전혀 사용되지 않은 4-5 테이블을 조인하고 있음을 발견했습니다. 이 테이블에 외래 키를 추가하는 것 외에는로드 시간이 90 % 단축되었습니다. 5 초 이상 걸린 쿼리는 이제 500ms 이하가 소요됩니다.

그것은 엄청나게 향상되었습니다!

그리고 다른 사람들이 언급했듯이 관계 무결성을 보장하는 추가 보너스를 얻습니다.

이 외에도 참조 무결성을 보장하는 것 자체 성능 이점도 있습니다. 외래 키가있는 테이블이 외래 테이블과 함께 '최신'이되도록하는 2 차 효과가 있습니다. 사용자 테이블과 주석 테이블이 있고 주석 테이블에 대한 통계를 수행한다고 가정하십시오. 사용자를 강제로 삭제하면 해당 사용자의 의견도 더 이상 원하지 않을 것입니다.


외래 키를 추가하기 전에 생성하는 데 필요한 인덱스가 테이블에 있습니까?
조지

1

테이블에 외래 키를 추가해도 성능이 향상되지 않습니다. 단순히 Product Categories 테이블 데이터베이스에 레코드를 삽입하는 경우 외래 키 열에 제품 테이블의 기본 키 값에 존재하는 값이 있는지 확인하려고합니다. Product Categories 테이블에 새 항목을 추가 할 때마다 데이터베이스에서 작업이 오버 헤드됩니다. 따라서 외래 키를 추가해도 데이터베이스 성능은 향상되지 않지만 데이터베이스의 무결성을 관리합니다. 그렇습니다. 프로그램의 데이터베이스에 레코드가 있는지 확인하기 위해 많은 쿼리를 실행하는 대신 외래 키를 사용하여 무결성을 검사하는 경우 db의 성능이 향상됩니다.


0

SQL Server에 대해 많이 알지 못하지만 Oracle의 경우 외래 키 열을 사용하면 데이터로드 성능이 저하됩니다. 데이터베이스가 각 삽입에 대한 데이터 무결성을 확인해야하기 때문입니다. 그리고 이미 언급했듯이 외래 키 열에 대한 색인을 갖는 것이 좋습니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.