Tăng Hiệu Suất Database trong ASP.NET Core
January 19, 2025Database là trái tim của hiệu suất ứng dụng, nhưng các truy vấn không hiệu quả có thể làm chậm thời gian phản hồi, tiêu tốn tài nguyên máy chủ, và thậm chí khiến ứng dụng bị timeout. Tối ưu hóa truy vấn database sẽ giảm tải, cải thiện hiệu suất và tăng trải nghiệm người dùng. Dưới đây là một số kỹ thuật để cải thiện hiệu suất gọi database trong ASP.NET Core C#.
1. Tránh Vấn Đề N+1 Queries
Vấn đề N+1 xảy ra khi ứng dụng thực hiện một truy vấn chính để lấy danh sách bản ghi, nhưng sau đó lại thực hiện thêm N truy vấn phụ cho từng bản ghi để lấy dữ liệu liên quan.
Ví dụ không tối ưu:
// Truy vấn đầu tiên, lấy danh sách articles
var articles = dbContext.Articles.ToList();
foreach (var article in articles)
{
// N truy vấn phụ: một cho mỗi article để lấy comments
var comments = dbContext.Comments
.Where(x => x.ArticleId == article.Id)
.ToList();
}
Nếu bảng Articles có 1000 bản ghi, thì sẽ có 1001 truy vấn được thực thi—rất tốn kém.
Giải pháp:
Sử dụng phương pháp Include() để tải dữ liệu liên quan trong một lần truy vấn.
var articles = dbContext.Articles
.Include(x => x.Comments)
.ToList();
2. Giảm Lượng Dữ Liệu Truyền Tải Bằng Projection
Nhiều trường hợp, developer lấy nhiều dữ liệu hơn mức cần thiết. Việc này tăng băng thông và tiêu tốn tài nguyên bộ nhớ.
Ví dụ không tối ưu:
// Lấy toàn bộ entity nhưng chỉ sử dụng một vài thuộc tính
var articles = dbContext.Articles.ToList();
var responseData = articles.Select(x => new { x.Title, x.Description });
Giải pháp:
Dùng projection để chỉ lấy những thuộc tính cần thiết.
var articles = dbContext.Articles
.Select(x => new { x.Title, x.Description })
.ToList();
3. Sử Dụng AsNoTracking() cho Truy Vấn Chỉ Đọc
Mặc định, Entity Framework Core theo dõi tất cả các entity được truy vấn. Nhưng nếu dữ liệu chỉ được sử dụng để đọc và không thay đổi, bạn nên tắt tính năng tracking này để giảm tải bộ nhớ.
Ví dụ không tối ưu:
public async Task<List<Article>> GetArticles()
{
return await _context.Articles.ToListAsync();
}
Giải pháp:
Thêm AsNoTracking() để tắt tính năng tracking.
public async Task<List<Article>> GetArticles()
{
return await _context.Articles.AsNoTracking().ToListAsync();
}
4. Tận Dụng Connection Pooling
Mỗi khi ứng dụng mở kết nối mới đến database, nó tiêu tốn tài nguyên đáng kể. Với connection pooling, bạn có thể tái sử dụng các kết nối sẵn có, giảm chi phí khởi tạo kết nối mới.
Cấu hình chuỗi kết nối:
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=test-db;User Id=sa;Password=myPwd;Max Pool Size=100;"
}
Parameter Max Pool Size giúp kiểm soát số lượng kết nối tối đa được sử dụng, cải thiện thời gian phản hồi và khả năng mở rộng.
Tóm lại, việc quản lý hiệu quả cách ứng dụng giao tiếp với database là yếu tố quan trọng để xây dựng ứng dụng hiệu suất cao. Một số lưu ý chính:
– Tránh N+1 Queries bằng cách sử dụng Include().
– Giảm dữ liệu không cần thiết bằng cách sử dụng projection với Select().
– Tắt tracking khi không cần thiết với AsNoTracking().
– Tối ưu hóa kết nối bằng connection pooling.
Các kỹ thuật này sẽ cải thiện đáng kể hiệu suất ứng dụng của bạn, đặc biệt với các dự án sử dụng Entity Framework Core trong ASP.NET Core C#.