針對未索引列的查詢
Optimize 提供建議,幫助您識別和解決因缺少資料庫索引而導致的效能問題。
以下針對 User 模型的查詢使用 where 屬性來過濾沒有索引的列:
await prisma.user.findFirst({
where: {
name: "Marc"
}
})
await prisma.user.findFirst({
where: {
name: "Jon"
}
})
await prisma.user.count({
where: {
name: "Nikolas"
}
})
問題是什麼?
索引允許資料庫更快地檢索資料,類似於書中的索引如何幫助您查詢資訊而無需閱讀每一頁。
當使用 Prisma 並帶有 where 屬性時,如果相關列沒有定義索引,資料庫可能需要掃描表中的每一行(即“全表掃描”)才能找到匹配項。這可能因以下幾個原因而不可取:
使用者體驗
對於大型資料集,如果資料庫必須掃描整個表才能找到匹配行,使用者將體驗到更長的等待時間。
資源利用
- 高 CPU 使用率: 掃描大表會顯著增加 CPU 使用率,從而降低整體系統效能。
- 記憶體消耗: 在全表掃描期間,需要更多記憶體來處理和儲存資料。
- 磁碟 I/O: 全表掃描會增加磁碟輸入/輸出操作,可能減慢其他資料庫活動。
警告
儘管這些問題可能在開發環境中因資料集較小而不會出現,但在生產環境中,由於資料集通常大得多,它們會成為顯著的問題。
更多關於資料庫索引
索引工作原理
索引建立了一個數據結構,用於儲存索引列的值以及指向表中相應行的指標。當您使用索引列查詢資料庫時,資料庫可以使用此索引快速定位相關行,而無需掃描整個表。
索引的權衡
- 空間與時間: 索引需要額外的儲存空間來儲存索引資料,但它顯著加快了資料檢索速度。
- 更新開銷: 每次向表中新增、更新或刪除資料時,都會有保持索引更新的開銷,這會減慢寫入操作。
何時使用索引
- 大型資料集: 索引對於行數眾多的表特別有利。
- 頻繁過濾或排序的查詢: 在經常用於過濾或排序的列上使用索引。
- 查詢相關資料: 在外部索引鍵列上使用索引可以加快相關記錄的檢索速度,例如在使用
include時。
何時不使用索引
- 小型表: 對於行數很少的表,維護索引的開銷可能不值得效能提升。
- 寫入密集型表: 索引會減慢寫入操作(
create、update、delete),因為索引也需要更新。避免對頻繁寫入操作的模型過度索引。 - 不常訪問的表: 如果一個表很少被訪問,索引的好處可能不足以彌補其開銷。
- 大資料量列: 對大資料量的列進行索引可能會導致更高的儲存需求,並且可能無法提供顯著的效能改進。
- 很少過濾的列: 如果一個表經常被訪問但很少透過特定列進行過濾,那麼在該列上建立索引可能沒有益處。
警告
即使您對某一列建立了索引,資料庫也可能不總是使用它。許多資料庫管理系統,如 PostgreSQL 和 MySQL,都有一個查詢最佳化器,它會評估多個執行計劃,並選擇其認為最高效的那個。在某些情況下,這可能涉及忽略現有索引,而選擇它認為對該特定查詢效能更好的不同執行計劃。