Đây là vấn đề mình gặp trong quá trình làm việc, viết vào đây vừa để note lại cho bản thân, vừa chia sẻ với mọi người.
Có 1 bảng users(id, name, created_date) 100tr bản ghi column created_date đã được đánh index
Yêu cầu đặt ra là lấy tất cả thông tin users của nhưng user được tạo trong năm 2020 Ban đầu mình cũng nghĩ dùng hàm year để tính năm rồi so sánh như thế này.
select *
from users u
where year(u.created_date) = 2020 ;
Ai nhìn cũng bảo dễ, viết là xong ngay, các bạn hay ngừng lại 5 phút suy nghĩ xem vấn đề nằm ở chỗ nào, có cách nào tối ưu hơn không?
Vấn đề
Sử dụng hàm year() làm mất index của cột bị đánh index và nó sẽ phải tính toán tất cả các giá trị trong bảng users rồi mới so sánh.
Giải pháp
Hạn chế dùng hàm để thay đổi giá trị của cột đã được đánh index. Trong bài toàn này, thay vì tính toán Year, chúng ta có thể so sánh với 2 mốc thời gian như bên dưới.
select *
from users u
where u.created_date >= '01-01-2020' && u.created_date < '01-01-2021' ;
Bằng cách này, chúng ta giữ được index, giảm thời gian querry.
Kết luận
Đây là 1 bài toán khá đơn giản, nhưng đôi khi chúng ta không để ý, nếu nó được sử dụng trong 1 câu query phức tạp, thì chúng ra khó mà phát hiện lỗi ở chỗ nào. Cần xử lý 1 cách cẩn thận từ các câu query nhỏ, hiểu rõ bản chất từ đó giúp chúng ta xử lý các câu query phức tạp hơn.
Nếu cần trao đổi, mọi người hãy comment bên dưới.