Saya membangun aplikasi web (sistem manajemen proyek) dan saya bertanya-tanya tentang ini ketika datang ke kinerja.
Saya memiliki tabel Issues dan di dalamnya terdapat 12 kunci asing yang terhubung ke berbagai tabel lainnya. dari mereka, 8 dari mereka saya akan perlu bergabung untuk mendapatkan judul dari tabel lain agar catatan masuk akal dalam aplikasi web tetapi kemudian berarti melakukan 8 bergabung yang tampaknya sangat berlebihan terutama karena saya hanya menarik 1 bidang untuk masing-masing bergabung.
Sekarang saya juga telah diberitahu untuk menggunakan kunci primer penambahan otomatis (kecuali jika sharding adalah masalah dalam hal mana saya harus menggunakan GUID) untuk alasan permanen, tetapi seberapa burukkah menggunakan performa varchar (panjang max 32)? Maksud saya sebagian besar tabel ini mungkin tidak akan memiliki banyak catatan (kebanyakan dari mereka harus di bawah 20). Juga jika saya menggunakan judul sebagai kunci utama, saya tidak perlu melakukan bergabung dengan 95% dari waktu jadi untuk 95% dari sql, saya bahkan akan terjadi hit kinerja (saya pikir). Satu-satunya downside yang dapat saya pikirkan adalah yang saya miliki adalah saya akan memiliki penggunaan ruang disk yang lebih tinggi (tapi turun satu hari adalah hal yang sangat besar).
Alasan saya menggunakan tabel pencarian untuk banyak hal ini alih-alih enum adalah karena saya perlu semua nilai ini dapat dikonfigurasi oleh pengguna akhir melalui aplikasi itu sendiri.
Apa kerugian menggunakan varchar sebagai kunci utama untuk tabel yang tidak terkecuali memiliki banyak catatan?
PEMBARUAN - Beberapa Tes
Jadi saya memutuskan untuk melakukan beberapa tes dasar tentang hal ini. Saya memiliki 100000 catatan dan ini adalah pertanyaan dasar:
Pangkalan VARCHAR FK Query
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
Basis INT FK Query
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
Saya juga menjalankan kueri ini dengan tambahan berikut:
- Pilih item tertentu (di mana i.key = 43298)
- Kelompokkan oleh i.id
- Dipesan oleh (it.title untuk int FK, i.issueTypeId untuk varchar FK)
- Batas (50000, 100)
- Kelompokkan dan batasi bersama
- Kelompokkan, pesan, dan batasi bersama
Hasil untuk ini di mana:
JENIS QUERY: WAKTU VARCHAR FK / WAKTU INT FK
Basis kueri: ~ 4ms / ~ 52ms
Pilih item tertentu: ~ 140ms / ~ 250ms
Kelompokkan oleh i.id: ~ 4ms / ~ 2.8sec
Dipesan oleh: ~ 231ms / ~ 2sec
Batas: ~ 67ms / ~ 343ms
Kelompokkan dan batasi bersama: ~ 504ms / ~ 2sec
Kelompokkan, pesan, dan batasi bersama: ~ 504ms / ~2.3sec
Sekarang saya tidak tahu konfigurasi apa yang bisa saya buat untuk membuat yang satu atau yang lain (atau keduanya) lebih cepat tetapi sepertinya VARCHAR FK melihat lebih cepat dalam permintaan data (kadang-kadang jauh lebih cepat).
Saya kira saya harus memilih apakah peningkatan kecepatan itu sepadan dengan data tambahan / ukuran indeks.