웹 응용 프로그램 (프로젝트 관리 시스템)을 구축 중이며 성능과 관련하여 궁금합니다.
내부에 Issues 테이블이 있으며 다양한 다른 테이블에 연결되는 12 개의 외래 키가 있습니다. 그중 8 개는 웹 응용 프로그램에서 레코드가 의미를 갖기 위해 다른 테이블에서 제목 필드를 가져 오기 위해 참여해야하지만 8 개의 조인을 수행하는 것을 의미합니다. 각 조인에 대해 1 개의 필드.
이제 영구 증가 이유로 샤딩이 GUID를 사용해야하는 경우가 아니라면 자동 증분 기본 키를 사용하라는 지시를 받았지만 varchar (최대 길이 32) 성능을 현명하게 사용하는 것은 얼마나 나쁩니 까? 나는이 테이블의 대부분이 아마도 많은 레코드를 가지고 있지 않을 것임을 의미합니다 (대부분 20 미만이어야 함). 또한 제목을 기본 키로 사용하면 95 %의 시간을 조인 할 필요가 없으므로 SQL의 95 %에서 성능 저하가 발생할 수 있습니다 (제 생각에). 내가 생각할 수있는 유일한 단점은 내가 가지고있는 디스크 공간 사용량이 높다는 것입니다 (그러나 하루는 실제로 큰 문제입니다).
열거 형 대신 많은 것들에 대해 조회 테이블을 사용하는 이유는 응용 프로그램 자체를 통해 최종 사용자가 구성 할 수있는 모든 값이 필요하기 때문입니다.
많은 레코드를 제외하고 varchar를 테이블의 기본 키로 사용하는 단점은 무엇입니까?
업데이트-일부 테스트
그래서 나는 이것에 대한 기본 테스트를하기로 결정했습니다. 나는 100000 개의 레코드를 가지고 있으며 이것이 기본 쿼리입니다.
기본 VARCHAR FK 쿼리
SELECT i.id, i.key, i.title, i.reporterUserUsername, i.assignedUserUsername, i.projectTitle,
i.ProjectComponentTitle, i.affectedProjectVersionTitle, i.originalFixedProjectVersionTitle,
i.fixedProjectVersionTitle, i.durationEstimate, i.storyPoints, i.dueDate,
i.issueSecurityLevelId, i.creatorUserUsername, i.createdTimestamp,
i.updatedTimestamp, i.issueTypeId, i.issueStatusId
FROM ProjectManagement.Issues i
기본 INT FK 쿼리
SELECT i.id, i.key, i.title, ru.username as reporterUserUsername,
au.username as assignedUserUsername, p.title as projectTitle,
pc.title as ProjectComponentTitle, pva.title as affectedProjectVersionTitle,
pvo.title as originalFixedProjectVersionTitle, pvf.title as fixedProjectVersionTitle,
i.durationEstimate, i.storyPoints, i.dueDate, isl.title as issueSecurityLevelId,
cu.username as creatorUserUsername, i.createdTimestamp, i.updatedTimestamp,
it.title as issueTypeId, is.title as issueStatusId
FROM ProjectManagement2.Issues i
INNER JOIN ProjectManagement2.IssueTypes `it` ON it.id = i.issueTypeId
INNER JOIN ProjectManagement2.IssueStatuses `is` ON is.id = i.issueStatusId
INNER JOIN ProjectManagement2.Users `ru` ON ru.id = i.reporterUserId
INNER JOIN ProjectManagement2.Users `au` ON au.id = i.assignedUserId
INNER JOIN ProjectManagement2.Users `cu` ON cu.id = i.creatorUserId
INNER JOIN ProjectManagement2.Projects `p` ON p.id = i.projectId
INNER JOIN ProjectManagement2.`ProjectComponents` `pc` ON pc.id = i.projectComponentId
INNER JOIN ProjectManagement2.ProjectVersions `pva` ON pva.id = i.affectedProjectVersionId
INNER JOIN ProjectManagement2.ProjectVersions `pvo` ON pvo.id = i.originalFixedProjectVersionId
INNER JOIN ProjectManagement2.ProjectVersions `pvf` ON pvf.id = i.fixedProjectVersionId
INNER JOIN ProjectManagement2.IssueSecurityLevels isl ON isl.id = i.issueSecurityLevelId
또한 다음 추가 사항으로 이러한 쿼리를 실행했습니다.
- 특정 항목을 선택하십시오 (여기서 i.key = 43298).
- i.id로 그룹화
- 정렬 기준 (int FK의 경우 제목, varchar FK의 경우 i.issueTypeId)
- 한도 (50000, 100)
- 그룹화 및 제한
- 그룹화, 주문 및 제한
이에 대한 결과는 다음과 같습니다.
쿼리 유형 : VARCHAR FK TIME / INT FK TIME
기본 쿼리 : ~ 4ms / ~ 52ms
특정 항목 선택 : ~ 140ms / ~ 250ms
i.id로 그룹화 : ~ 4ms / ~ 2.8sec
주문 : ~ 231ms / ~ 2sec
제한 : ~ 67ms / ~ 343ms
그룹화 및 제한 : ~ 504ms / ~ 2sec
그룹화, 주문 및 제한 : ~ 504ms /~2.3sec
이제 하나 또는 다른 (또는 둘 다) 더 빠르게 만들 수있는 구성을 모르지만 VARCHAR FK가 데이터 쿼리에서 더 빨리 보이는 것처럼 보입니다 (때로는 훨씬 더 빠릅니다).
속도 향상이 추가 데이터 / 인덱스 크기의 가치가 있는지 여부를 선택해야한다고 생각합니다.