Giới thiệu
Trong các dự án fullstack sử dụng Prisma làm ORM cho MySQL, việc tối ưu truy vấn là yếu tố quyết định tốc độ phản hồi của API. Bài viết sẽ phân tích chi tiết các kỹ thuật tối ưu schema, cách viết truy vấn hiệu quả và cách quản lý kết nối database để giảm thiểu latency.
Tối ưu schema Prisma cho MySQL
Định nghĩa index phù hợp
MySQL chỉ sử dụng index khi các cột được khai báo trong @@index hoặc @id. Khi thiết kế schema, hãy xác định các cột thường dùng trong where hoặc orderBy và tạo index cho chúng.
model Product {
id Int @id @default(autoincrement())
name String
price Decimal
categoryId Int
createdAt DateTime @default(now())
@@index([price]) // Tìm kiếm theo giá
@@index([categoryId, price]) // Lọc theo danh mục + giá
}
Sử dụng select và include một cách hợp lý
Việc lấy toàn bộ trường của một bảng sẽ gây lãng phí băng thông và bộ nhớ. Thay vào đó, chỉ chọn những trường thực sự cần thiết.
const products = await prisma.product.findMany({
where: { price: { gt: 100 } },
select: {
id: true,
name: true,
price: true,
// Không lấy các trường không cần thiết như description, images
},
});
Batching và transaction để giảm round‑trip
Batch queries với prisma.$transaction
Khi cần thực hiện nhiều truy vấn liên tiếp, việc gọi riêng lẻ sẽ tạo nhiều kết nối tới MySQL. Sử dụng prisma.$transaction để gộp chúng thành một lần round‑trip.
await prisma.$transaction([
prisma.order.create({ data: { userId, total: 0 } }),
prisma.orderItem.createMany({
data: items.map(item => ({
orderId: /* order id sẽ được trả về từ query trên */,
productId: item.id,
quantity: item.qty,
})),
}),
]);
Kiểm soát kết nối và pool trong MySQL
Prisma dựa trên mysql2 driver, cho phép cấu hình pool kết nối. Đặt connection_limit phù hợp với tài nguyên server để tránh quá tải.
# .env DATABASE_URL="mysql://user:password@localhost:3306/ecommerce?connection_limit=10"
Trong môi trường Docker, bạn cũng nên khai báo max_connections trong my.cnf để đồng bộ với giá trị trên.
Kỹ thuật cache query với TanStack Query
Ở phía client, TanStack Query giúp cache dữ liệu và tự động refetch khi cần. Đặt thời gian staleTime hợp lý để giảm số lần gọi API.
const { data, isLoading } = useQuery(['products', minPrice], async () => {
const res = await fetch(`/api/products?minPrice=${minPrice}`);
return res.json();
}, {
staleTime: 5 * 60 * 1000, // 5 phút
});
Kết luận
Áp dụng các biện pháp trên – tạo index đúng chỗ, giảm trường trả về, batch các truy vấn và cấu hình pool hợp lý – sẽ giúp API của bạn phản hồi nhanh hơn đáng kể. Để nắm bắt toàn bộ quy trình xây dựng một Ecommerce Dashboard từ đầu tới cuối, bạn có thể Tham khảo khóa học "[Full Course] Ecommerce Dashboard Fullstack Clone" tại đây.








