Tối ưu hiệu năng SQL (phần 1): DATETIME

Dạo này viết lan man nhiều thứ quá nên mình quyết định muốn tập trung vào 1 cái gì đó nhiều hơn. Chính vì vậy mình cho sẽ cho ra mắt series Tối ưu hiệu năng SQL, một chủ đề khá là rộng cũng như là một chủ đề khó :v Tất cả những gì trong series này sẽ là những thứ mình đã học được trong thời gian làm việc cũng như tìm tòi (chủ yếu thông qua stackoverflow :v) Có thể các kiến thức mình đưa ra trong bài viết chưa có độ chính xác lắm nên mọi người có thể đóng góp cho mình cái này :3

Anh em mà google thì có mà ra cả đống mấy bài viết kiểu này quanh đi thì hầu như kiểu là UION thì nên UNION ALL, SELECT trường cần chứ không SELECT *, INDEX các trường cần truy vấn…

indexcartoon

Mấy cái này thì chắc anh em làm CSDL đều nắm khá rõ tuy nhiên đối với cách áp dụng thì hầu như là khó vì không gặp nhiều :)) Vì thế mình mong với series này mọi người sẽ hiểu nhiều hơn để áp dụng cho các project của mình :3

Trong ứng dụng doanh nghiệp thì mấy việc tìm kiếm theo ngày tháng thì thôi khỏi nói rồi đấy là điều tất lẽ dĩ ngẫu mà chức năng nào đều phải có :v Tuy nhiên thì mình thấy việc thực hiện điều này ở công ty mình có khá nhiều điều cần phải xem xét lại.

Thực tế thì mấy cái chương trình bên mình thì có cái kiểu bảng A có cái cột C đi, cột C thì để kiểu Datetime. Còn trong ứng dụng thì mình có thực hiện truy vấn trên cái bảng A với điều kiện tìm kiếm trên cột C kiểu từ ngày đến ngày tuy nhiên thì giá trị truyền vào là kiểu Date không có time ví như 16/09/2016 chứ không phải 16/09/2016 20:00:00. Chính vì thế nên nếu để từ ngày = đến ngày như 16/09/2016 thì không cẩn thận dễ bị lỗi không query ra được :v.

SELECT * FROM A WHERE C BETWEEN @FROM AND @TO

Cách này thì khỏi nói vì sai rồi :v Bên mình hay kiểu là CONVERT sang VARCHAR rồi mới so sánh

SELECT * FROM A WHERE CONVERT(VARCHAR(10), C, 120) >= CONVERT(VARCHAR(10), @FROM, 120) AND CONVERT(VARCHAR(10), C, 120) <= CONVERT(VARCHAR(10), @TO, 120)

Kết quả ra thì sẽ ok ngay tuy nhiên lại có 1 vấn đề chính của chủ đề hôm nay đó là HIỆU NĂNG.

Theo mấy cái lý thuyết về hiệu năng thì khi chúng ta áp dụng FUNCTION CONVERT cho cột C thì nếu 500 anh em đánh INDEX trên cột C thì nó sẽ mất tác dụng 😐 Đau chưa 😐 Câu truy vấn kia thôi là TABLE SCAN luôn không áp dụng được INDEX SCAN.

Chưa kể đó là khi anh em ta có bảng với hàng ngàn, hàng triệu dòng thì việc áp dụng tính toán cho 1 cột nào đó

Vậy cách tối ưu nhất là gì? là gì? là gì?

4b4455deb131c305c89c1041b5aece78206e90c55f17a171215ee18d450d0f14

Anh em copy code nhé :v

SELECT * FROM A WHERE(C >= CAST(@FROM AS DATE)) AND (C< DATEADD(dd, 1, CAST(@TO AS DATE)))

Lưu ý: là BETWEEN sẽ không thể sử dụng ở đây được vì BETWEEN sử dụng >= và <=

Với cách trên thì đảm bảo được việc tìm kiếm cũng như hiệu năng của ứng dụng nếu sử dụng INDEX. Đấy là cách của bây giờ chứ hồi xưa các cụ làm vất vả lắm phải qua mấy bước cơ:

Cast kiểu DATETIME thành kiểu FLOAT
Bỏ phần time
CAST lại kiểu thành DATETIME
Ví dụ: CAST (FLOOR (CAST (C AS FLOAT)) AS DATETIME)

HÊT PHẦN 1

Advertisements

5 thoughts on “Tối ưu hiệu năng SQL (phần 1): DATETIME

  1. Pingback: Tối ưu SQL (phần 9): tính tổng các dòng | Code, code and more code

  2. Pingback: Tập tành xử lý ảnh (phần 1: ảnh ở đâu ra?) | Code, code and more code

  3. Pingback: Tối ưu SQL phần 8: 1 câu chuyện đơn gian về việc cộng chuỗi | Code, code and more code

  4. Pingback: Tối ưu SQL (phần 7): Chuyện ngắn của ID | Code, code and more code

  5. Pingback: Tối ưu hiệu năng SQL (phần ): Update hay Merge? | Code, code and more code

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s