ฉันสร้างเว็บแอปพลิเคชัน (ระบบการจัดการโครงการ) และฉันสงสัยเกี่ยวกับสิ่งนี้เมื่อพูดถึงประสิทธิภาพ
ฉันมีตารางปัญหาอยู่ข้างในนั้นมี 12 ปุ่มต่างประเทศที่เชื่อมโยงกับตารางอื่น ๆ ในบรรดา 8 คนนั้นฉันต้องเข้าร่วมเพื่อรับฟิลด์ชื่อเรื่องจากตารางอื่น ๆ เพื่อให้ระเบียนมีเหตุผลในแอปพลิเคชันเว็บ 1 ฟิลด์สำหรับการรวมแต่ละรายการ
ตอนนี้ฉันยังได้รับคำสั่งให้ใช้คีย์หลักที่เพิ่มขึ้นอัตโนมัติ (ยกเว้นการใช้เศษเป็นข้อกังวลในกรณีที่ฉันควรใช้ GUID) สำหรับเหตุผลด้านความคงทน แต่มันแย่ขนาดไหนในการใช้ varchar (ความยาวสูงสุด 32) ฉันหมายถึงส่วนใหญ่ของตารางเหล่านี้อาจไม่ได้มีการบันทึกจำนวนมาก (ส่วนใหญ่ควรต่ำกว่า 20) นอกจากนี้ถ้าฉันใช้ชื่อเป็นคีย์หลักฉันจะไม่ต้องรวม 95% ของเวลาดังนั้นสำหรับ 95% ของ sql ฉันจะเกิดผลการทำงานที่ยอดเยี่ยม (ฉันคิดว่า) ข้อเสียอย่างเดียวที่ฉันคิดได้ก็คือฉันมีคือฉันจะมีการใช้พื้นที่ดิสก์ที่สูงขึ้น
เหตุผลที่ฉันใช้ตารางการค้นหาสำหรับสิ่งนี้มากมายแทนที่จะเป็น enums ก็เพราะฉันต้องการค่าทั้งหมดเหล่านี้เพื่อกำหนดค่าโดยผู้ใช้ผ่านแอปพลิเคชันเอง
อะไรคือข้อเสียของการใช้ varchar เป็นคีย์หลักสำหรับตารางที่ไม่ได้ยกเว้นที่จะมีหลายระเบียน?
อัพเดท - การทดสอบบางอย่าง
ดังนั้นฉันจึงตัดสินใจทำการทดสอบเบื้องต้นเกี่ยวกับสิ่งนี้ ฉันมีบันทึก 100,000 รายการและนี่คือการสืบค้นพื้นฐาน:
แบบสอบถาม 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
- สั่งซื้อโดย (it.title สำหรับ int FK, i.issueTypeId สำหรับ varchar FK)
- ขีด จำกัด (50000, 100)
- จัดกลุ่มและ จำกัด ร่วมกัน
- จัดกลุ่มคำสั่งซื้อและ จำกัด ร่วมกัน
ผลลัพธ์สำหรับสิ่งเหล่านี้ที่:
QUERY TYPE: VARCHAR FK TIME / INT FK TIME
ข้อความค้นหาพื้นฐาน: ~ 4ms / ~ 52ms
เลือกรายการเฉพาะ: ~ 140ms / ~ 250ms
จัดกลุ่มตาม i.id: ~ 4ms / ~ 2.8sec
เรียงลำดับโดย: ~ 231ms / ~ 2 วินาที
จำกัด : ~ 67ms / ~ 343ms
จัดกลุ่มและ จำกัด ร่วมกัน: ~ 504ms / ~ 2 วินาที
จัดกลุ่มคำสั่งซื้อและ จำกัด ด้วยกัน: ~ 504ms /~2.3 วินาที
ตอนนี้ฉันไม่ทราบว่าการกำหนดค่าใดที่ฉันสามารถทำได้เพื่อทำให้เร็วขึ้น (หรือทั้งสองอย่าง) แต่ดูเหมือนว่า VARCHAR FK จะดูเร็วขึ้นในการสืบค้นข้อมูล (บางครั้งเร็วกว่ามาก)
ฉันเดาว่าฉันต้องเลือกว่าการปรับปรุงความเร็วนั้นคุ้มค่ากับขนาดข้อมูล / ดัชนีพิเศษหรือไม่