Kiến thức Hữu ích 😍

Các kiểu dữ liệu trong MySQL: Phân loại, đặc điểm & cách dùng hiệu quả


Việc xây dựng một cơ sở dữ liệu cũng giống như xây dựng một ngôi nhà. Bạn không thể dùng cùng một loại vật liệu cho mọi thứ. Bạn cần gạch để xây tường, kính để làm cửa sổ, và gỗ cho sàn nhà. Trong MySQL, “vật liệu” đó chính là các kiểu dữ liệu. Việc chọn đúng kiểu dữ liệu cho từng cột thông tin không chỉ là một lựa chọn kỹ thuật, mà là nền tảng quyết định đến hiệu suất, sự ổn định và khả năng mở rộng của toàn bộ hệ thống.

Nhiều người mới bắt đầu thường mắc phải sai lầm là chọn kiểu dữ liệu một cách qua loa, ví dụ như dùng VARCHAR cho mọi thứ hoặc INT cho những con số chỉ cần phạm vi rất nhỏ. Điều này ban đầu có vẻ vô hại, nhưng khi dữ liệu phình to, hệ thống sẽ trở nên chậm chạp, tốn dung lượng lưu trữ và khó bảo trì. Bài viết này sẽ là kim chỉ nam giúp bạn hiểu rõ từng loại kiểu dữ liệu trong MySQL, từ phân loại, đặc điểm, cho đến cách áp dụng chúng một cách thông minh và hiệu quả nhất.

Phân loại các kiểu dữ liệu phổ biến trong MySQL

MySQL cung cấp một hệ thống kiểu dữ liệu đa dạng, được chia thành các nhóm chính để phục vụ những mục đích lưu trữ khác nhau. Hiểu rõ từng nhóm sẽ giúp bạn đưa ra lựa chọn chính xác ngay từ đầu.

Hình minh họa

Kiểu dữ liệu số nguyên (Integer)

Đây là nhóm dùng để lưu trữ các số không có phần thập phân, như số đếm, ID, hoặc tuổi tác. Việc chọn đúng loại số nguyên sẽ giúp bạn tiết kiệm đáng kể dung lượng.

  • TINYINT: Là loại nhỏ nhất, chỉ chiếm 1 byte. Nó có thể lưu trữ các giá trị từ -128 đến 127 (hoặc 0 đến 255 nếu dùng UNSIGNED). Rất lý tưởng để lưu trữ tuổi của một người, số lượng con cái, hoặc các trạng thái có ít lựa chọn (ví dụ: 0 = chờ xử lý, 1 = đã duyệt, 2 = bị từ chối).
  • SMALLINT: Chiếm 2 byte, với phạm vi từ -32,768 đến 32,767. Phù hợp cho các cột dữ liệu có số lượng không quá lớn, ví dụ như số lượng sản phẩm trong một danh mục nhỏ.
  • MEDIUMINT: Chiếm 3 byte, ít được sử dụng nhưng hữu ích trong một số trường hợp cụ thể, với phạm vi lên đến hơn 8 triệu.
  • INT (INTEGER): Là lựa chọn phổ biến nhất, chiếm 4 byte. Phạm vi của nó lên tới hơn 2 tỷ, đủ cho hầu hết các nhu cầu như lưu ID người dùng, ID bài viết, hay số lượng lượt xem. Tham khảo thêm SQL là gì để hiểu rõ hơn về cách sử dụng ngôn ngữ truy vấn SQL liên quan đến kiểu dữ liệu số nguyên.
  • BIGINT: Chiếm 8 byte, dành cho những con số khổng lồ. Hãy nghĩ đến số lượt xem của một video viral trên YouTube, số dư tài khoản ngân hàng tính bằng đơn vị nhỏ nhất, hoặc ID trong các hệ thống cực lớn.

Kiểu dữ liệu số thực (Floating-point)

Khi bạn cần lưu trữ các số có phần thập phân như giá cả, trọng lượng, hoặc tọa độ địa lý, nhóm số thực là lựa chọn của bạn.

  • FLOAT và DOUBLE: Hai kiểu này lưu trữ các giá trị số thực dạng gần đúng. FLOAT sử dụng 4 byte và có độ chính xác thấp hơn DOUBLE (sử dụng 8 byte). Chúng phù hợp cho các phép đo khoa học, vật lý nơi một sự sai khác nhỏ không gây ảnh hưởng lớn. Tuy nhiên, tuyệt đối không dùng chúng để lưu trữ dữ liệu tài chính vì có thể gây ra lỗi làm tròn không mong muốn.
  • DECIMAL (NUMERIC): Đây là kiểu dữ liệu số thực có độ chính xác tuyệt đối. Bạn có thể định nghĩa tổng số chữ số và số chữ số sau dấu phẩy (ví dụ: DECIMAL(10, 2)). Đây là lựa chọn bắt buộc khi làm việc với tiền tệ, điểm số, hoặc bất kỳ dữ liệu nào yêu cầu sự chính xác 100%. Khái quát về cách sử dụng và ưu điểm của DECIMAL cũng được đề cập trong bài viết Database Index là gì nơi tác động của kiểu dữ liệu đến hiệu suất được phân tích.

Hình minh họa

Kiểu dữ liệu chuỗi ký tự (String)

Nhóm này dùng để lưu trữ văn bản, từ một ký tự đơn lẻ đến cả một cuốn sách.

  • CHAR(n): Lưu trữ chuỗi có độ dài cố định. Nếu bạn khai báo CHAR(10) và chỉ lưu chữ “AZWEB”, nó vẫn chiếm đủ 10 ký tự trong bộ nhớ bằng cách thêm các khoảng trắng vào cuối. CHAR rất hiệu quả cho các dữ liệu luôn có độ dài không đổi, như mã quốc gia (“VN”, “US”), mã bưu chính, hoặc các giá trị hash MD5.
  • VARCHAR(n): Lưu trữ chuỗi có độ dài thay đổi, và đây là kiểu dữ liệu chuỗi phổ biến nhất. Nếu bạn khai báo VARCHAR(255) và lưu chữ “AZWEB”, nó chỉ chiếm dung lượng của 5 ký tự cộng thêm 1-2 byte để lưu thông tin độ dài. Rất phù hợp cho tên người dùng, tiêu đề bài viết, email, địa chỉ. Để khai thác tối ưu MySQL Workbench cho việc thiết kế bảng với các kiểu ký tự này là điều bạn nên tìm hiểu thêm.
  • TEXT: Khi VARCHAR không đủ lớn, TEXT là giải pháp. Nó có các biến thể như TINYTEXT, TEXT, MEDIUMTEXT, và LONGTEXT để lưu trữ những đoạn văn bản dài như nội dung bình luận, mô tả sản phẩm chi tiết, hoặc toàn bộ nội dung của một bài blog.

Kiểu dữ liệu ngày giờ (Date-Time)

Việc lưu trữ và truy vấn dữ liệu liên quan đến thời gian là một phần không thể thiếu của mọi ứng dụng. MySQL cung cấp nhiều kiểu dữ liệu chuyên dụng.

  • DATE: Chỉ lưu ngày, tháng, năm theo định dạng YYYY-MM-DD. Lý tưởng cho việc lưu ngày sinh, ngày hết hạn. Hãy tham khảo thêm bài viết Query là gì để nắm được cách sử dụng các truy vấn liên quan khai thác kiểu dữ liệu ngày tháng chính xác.
  • TIME: Chỉ lưu giờ, phút, giây theo định dạng HH:MM:SS. Dùng để lưu giờ mở cửa, thời gian của một sự kiện trong ngày.
  • DATETIME: Lưu trữ cả ngày và giờ, từ năm 1000 đến 9999. Hoàn hảo để ghi lại thời điểm một bài viết được xuất bản, một đơn hàng được tạo.
  • TIMESTAMP: Cũng lưu cả ngày và giờ nhưng có một số khác biệt quan trọng. Phạm vi của nó nhỏ hơn (1970-01-01 đến 2038-01-19). TIMESTAMP tự động chuyển đổi múi giờ và có thể tự động cập nhật giá trị hiện tại mỗi khi bản ghi được thay đổi. Vì vậy, nó cực kỳ hữu ích cho các cột như created_at hay updated_at.
  • YEAR: Dùng để lưu trữ năm, có thể ở định dạng 2 hoặc 4 chữ số.

Hình minh họa

Đặc điểm và cách sử dụng từng kiểu dữ liệu

Hiểu rõ phân loại là bước đầu tiên. Bước tiếp theo là biết cách khai báo và nhận thức được ảnh hưởng của chúng đến hệ thống của bạn.

Cách khai báo và định dạng dữ liệu trong bảng MySQL

Khi tạo một bảng mới, bạn cần chỉ định tên cột và kiểu dữ liệu tương ứng. Cú pháp rất đơn giản nhưng đòi hỏi sự chính xác.

Hãy xem một ví dụ về việc tạo bảng products cho một trang web thương mại điện tử:

CREATE TABLE products (
    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    sku VARCHAR(50) NOT NULL UNIQUE,
    product_name VARCHAR(255) NOT NULL,
    price DECIMAL(10, 2) NOT NULL,
    stock_quantity SMALLINT UNSIGNED DEFAULT 0,
    published_date DATE,
    last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

Hãy cùng phân tích từng dòng:

  • id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY: ID sản phẩm là một số nguyên không âm (UNSIGNED), tự động tăng (AUTO_INCREMENT), và là khóa chính. Để hiểu kỹ hơn về cơ bản lệnh và câu lệnh trong quản lý dữ liệu, xem thêm ở bài SQL Server là gì.
  • sku VARCHAR(50) NOT NULL UNIQUE: Mã SKU là một chuỗi ký tự dài tối đa 50 ký tự, không được để trống (NOT NULL) và phải là duy nhất (UNIQUE).
  • price DECIMAL(10, 2) NOT NULL: Giá sản phẩm được định dạng với tổng 10 chữ số, trong đó có 2 chữ số sau dấu phẩy. Điều này đảm bảo tính chính xác tuyệt đối cho giá tiền.
  • stock_quantity SMALLINT UNSIGNED DEFAULT 0: Số lượng tồn kho là một số nguyên dương nhỏ, mặc định là 0. Dùng SMALLINT thay vì INT giúp tiết kiệm dung lượng.
  • published_date DATE: Ngày sản phẩm được đăng bán.
  • last_updated TIMESTAMP ...: Cột này tự động ghi lại thời điểm bản ghi được tạo và tự động cập nhật mỗi khi có thay đổi.

Hình minh họa

Ảnh hưởng của kiểu dữ liệu đến hiệu suất và dung lượng lưu trữ

Lựa chọn kiểu dữ liệu không chỉ là về tính đúng đắn mà còn là về tối ưu hóa. Một lựa chọn sai có thể làm lãng phí tài nguyên và làm chậm tốc độ truy vấn một cách không cần thiết.

Hãy tưởng tượng bạn có một bảng users với 1 triệu người dùng. Nếu bạn lưu tuổi của họ (giá trị không bao giờ vượt quá 255) bằng kiểu INT (4 byte) thay vì TINYINT (1 byte), bạn đã lãng phí: (4 byte - 1 byte) * 1,000,000 = 3,000,000 byte tức là gần 3MB chỉ cho một cột.

Sự lãng phí này không chỉ dừng lại ở dung lượng ổ cứng. Khi bạn truy vấn dữ liệu, MySQL cần đọc nhiều dữ liệu hơn từ đĩa vào bộ nhớ (RAM). Dữ liệu càng nhỏ gọn, càng nhiều bản ghi có thể được nạp vào RAM, giúp các thao tác tìm kiếm, sắp xếp và kết nối bảng (JOIN) diễn ra nhanh hơn đáng kể. Các chỉ mục (index) trên các cột có kiểu dữ liệu nhỏ hơn cũng sẽ nhỏ hơn, chiếm ít bộ nhớ hơn và tăng tốc độ truy vấn. Đây là lý do tại sao nguyên tắc vàng là: “Luôn chọn kiểu dữ liệu nhỏ nhất có thể đáp ứng được yêu cầu của bạn”.

Tầm quan trọng của việc chọn kiểu dữ liệu phù hợp trong thiết kế cơ sở dữ liệu

Việc chọn kiểu dữ liệu đúng đắn ngay từ đầu là một trong những quyết định quan trọng nhất khi thiết kế cơ sở dữ liệu. Nó ảnh hưởng sâu sắc đến mọi khía cạnh của hệ thống, từ hiện tại đến tương lai.

Hình minh họa

Ảnh hưởng đến tính toàn vẹn dữ liệu và bảo mật

Kiểu dữ liệu hoạt động như một người bảo vệ ở cấp độ cơ sở dữ liệu. Nó thiết lập các quy tắc nghiêm ngặt về loại thông tin nào được phép lưu trữ trong một cột.

Ví dụ, nếu bạn định nghĩa một cột là DATE, MySQL sẽ tự động từ chối bất kỳ nỗ lực nào nhằm chèn một giá trị không hợp lệ như “ngày mai” hay “32/13/2023”. Điều này đảm bảo rằng mọi dữ liệu trong cột đó đều tuân thủ một định dạng nhất quán và hợp lệ, giúp ngăn ngừa lỗi và giữ cho dữ liệu sạch sẽ. Tương tự, nếu một cột số lượng được khai báo là UNSIGNED, cơ sở dữ liệu sẽ không cho phép lưu trữ giá trị âm. Đây là một lớp phòng thủ quan trọng, giúp duy trì tính toàn vẹn dữ liệu ngay cả khi logic trong ứng dụng của bạn có sai sót.

Ảnh hưởng đến khả năng mở rộng và bảo trì hệ thống

Một hệ thống được thiết kế tốt với các kiểu dữ liệu phù hợp sẽ dễ dàng mở rộng và bảo trì hơn rất nhiều. Hãy nghĩ về tương lai. Nếu bạn đang xây dựng một mạng xã hội và chọn INT (phạm vi ~2 tỷ) cho cột user_id, bạn đã có một nền tảng vững chắc để phát triển. Nhưng nếu bạn chọn MEDIUMINT (phạm vi ~8 triệu) để tiết kiệm 1 byte, bạn có thể phải đối mặt với một cuộc khủng hoảng khi lượng người dùng vượt qua giới hạn đó.

Việc thay đổi kiểu dữ liệu trên một bảng đã chứa hàng triệu hoặc hàng tỷ bản ghi là một công việc cực kỳ tốn kém và rủi ro. Nó có thể yêu cầu khóa bảng trong một thời gian dài, gây gián đoạn dịch vụ. Bằng cách lựa chọn đúng ngay từ đầu, bạn đã tối ưu hóa cho sự phát triển trong tương lai, giảm thiểu chi phí bảo trì và nâng cấp sau này. Một lược đồ cơ sở dữ liệu rõ ràng, tự mô tả (self-documenting) cũng giúp các nhà phát triển mới nhanh chóng nắm bắt cấu trúc và làm việc hiệu quả hơn.

Một số vấn đề thường gặp và cách khắc phục

Ngay cả những nhà phát triển kinh nghiệm đôi khi cũng mắc phải những sai lầm liên quan đến kiểu dữ liệu. Nhận biết sớm các vấn đề này và biết cách khắc phục là một kỹ năng quan trọng.

Hình minh họa

Vấn đề chọn sai kiểu dữ liệu dẫn đến lỗi hoặc hiển thị sai

Đây là một trong những lỗi phổ biến nhất và có thể gây ra những hậu quả khó lường.

  • Ví dụ 1: Lưu trữ ngày tháng dưới dạng chuỗi (VARCHAR)
    • Vấn đề: Bạn lưu ngày sinh dưới dạng ‘DD-MM-YYYY’ trong cột VARCHAR. Thoạt nhìn, mọi thứ có vẻ ổn. Nhưng khi bạn cố gắng sắp xếp người dùng theo ngày sinh, kết quả sẽ sai hoàn toàn vì nó sắp xếp theo thứ tự chữ cái (’01-02-2000′ sẽ đứng sau ’31-01-2000′). Bạn cũng không thể thực hiện các phép toán ngày tháng, ví dụ như tìm tất cả người dùng sinh trong tháng 12.
    • Cách khắc phục: Chuyển đổi cột sang kiểu DATE. Bạn có thể cần viết một kịch bản (script) để đọc dữ liệu cũ, định dạng lại và cập nhật vào cột mới. Sử dụng hàm STR_TO_DATE() của MySQL có thể giúp ích trong quá trình này.
  • Ví dụ 2: Lưu trữ số điện thoại dưới dạng số (INT hoặc BIGINT)
    • Vấn đề: Số điện thoại ‘0912345678’ khi lưu vào cột số nguyên sẽ bị biến thành ‘912345678’, làm mất số 0 đứng đầu. Điều này làm cho dữ liệu trở nên vô dụng.
    • Cách khắc phục: Luôn lưu trữ các giá trị giống số nhưng không dùng để tính toán (như số điện thoại, mã zip, số CMND/CCCD) dưới dạng VARCHAR.

Khó khăn khi thay đổi kiểu dữ liệu sau khi đã có dữ liệu lớn

Khi hệ thống của bạn đã đi vào hoạt động và có một lượng dữ liệu khổng lồ, việc thay đổi kiểu dữ liệu của một cột trở thành một thách thức lớn.

Lệnh ALTER TABLE your_table MODIFY a_column NEW_DATA_TYPE; có thể khiến MySQL tạo một bản sao của toàn bộ bảng với cấu trúc mới, sao chép tất cả dữ liệu qua, rồi mới xóa bảng cũ. Với các bảng lớn, quá trình này có thể mất hàng giờ và sẽ khóa bảng, khiến ứng dụng của bạn không thể truy cập được.

Tư vấn giải pháp an toàn:

  1. Luôn luôn sao lưu (Backup): Trước khi thực hiện bất kỳ thay đổi cấu trúc nào, hãy tạo một bản sao lưu đầy đủ của cơ sở dữ liệu.
  2. Thử nghiệm trên môi trường Staging: Thực hiện thay đổi trên một môi trường giả lập có dữ liệu tương tự để đo lường thời gian cần thiết và phát hiện các vấn đề tiềm ẩn.
  3. Sử dụng công cụ chuyên dụng: Đối với các hệ thống trực tuyến quan trọng, hãy sử dụng các công cụ như pt-online-schema-change (từ Percona Toolkit) hoặc gh-ost (từ GitHub). Các công cụ này hoạt động bằng cách tạo một bảng tạm, sao chép dữ liệu dần dần mà không khóa bảng gốc, và cuối cùng hoán đổi chúng một cách nhanh chóng.
  4. Lên kế hoạch cho thời gian chết (Downtime): Nếu không thể sử dụng các công cụ trên, hãy lên lịch thực hiện thay đổi trong thời gian có lưu lượng truy cập thấp nhất (ví dụ: nửa đêm).

Hình minh họa

Lời khuyên và kinh nghiệm khi làm việc với kiểu dữ liệu MySQL

Dưới đây là những kinh nghiệm được đúc kết để giúp bạn làm việc với kiểu dữ liệu MySQL một cách hiệu quả và chuyên nghiệp.

  • Xác định chính xác yêu cầu lưu trữ: Trước khi chọn một kiểu dữ liệu, hãy tự hỏi: Giá trị lớn nhất và nhỏ nhất có thể là gì? Dữ liệu có cần giá trị âm không? (Nếu không, hãy dùng UNSIGNED). Dữ liệu có cần phần thập phân không? Sự chính xác có quan trọng không? Trả lời những câu hỏi này sẽ dẫn bạn đến lựa chọn đúng.
  • Ưu tiên dùng kiểu dữ liệu nhỏ nhất đủ dùng: Đây là nguyên tắc vàng để tiết kiệm tài nguyên. Đừng dùng INT nếu TINYINT là đủ. Đừng dùng VARCHAR(255) cho một cột chỉ để lưu mã quốc gia 2 ký tự. Tối ưu hóa từ những chi tiết nhỏ sẽ tạo ra sự khác biệt lớn.
  • Tránh sử dụng TEXT hoặc BLOB nếu có thể: Các kiểu dữ liệu này được xử lý khác với các kiểu dữ liệu có độ dài cố định hoặc VARCHAR, thường được lưu trữ ngoài trang dữ liệu chính. Điều này có thể làm chậm các truy vấn. Nếu bạn biết chắc rằng dữ liệu của mình sẽ không vượt quá giới hạn của VARCHAR (65,535 ký tự), hãy ưu tiên sử dụng nó.
  • Kiểm tra kỹ dữ liệu để chọn kiểu ngày giờ phù hợp: Bạn có cần lưu trữ thông tin múi giờ không? Nếu có, TIMESTAMP là lựa chọn tốt. Nếu bạn chỉ cần lưu một ngày cố định không phụ thuộc múi giờ (như ngày sinh), DATE hoặc DATETIME sẽ phù hợp hơn. Đừng lưu trữ thông tin bạn không cần.
  • Luôn sao lưu trước khi thay đổi cấu trúc: Lời khuyên này không bao giờ là thừa. Một lệnh ALTER TABLE sai lầm có thể gây mất dữ liệu. Một bản sao lưu là tấm vé bảo hiểm an toàn nhất của bạn.

Hình minh họa

Kết luận

Kiểu dữ liệu là viên gạch nền tảng của bất kỳ cơ sở dữ liệu MySQL nào. Việc hiểu rõ sự khác biệt giữa các kiểu số, chuỗi, và ngày giờ, cùng với việc áp dụng chúng một cách chính xác, là kỹ năng cốt lõi của một nhà phát triển hay quản trị viên cơ sở dữ liệu giỏi. Lựa chọn đúng đắn không chỉ giúp tiết kiệm dung lượng và tăng tốc độ truy vấn, mà còn đảm bảo tính toàn vẹn dữ liệu và tạo ra một hệ thống vững chắc, dễ dàng bảo trì và mở rộng trong tương lai.

Hy vọng qua bài viết này của AZWEB, bạn đã có cái nhìn toàn diện và sâu sắc hơn về thế giới các kiểu dữ liệu trong MySQL. Đừng chỉ đọc và ghi nhớ, hãy áp dụng kiến thức này ngay hôm nay. Thử mở một dự án cũ của bạn và rà soát lại các kiểu dữ liệu đã chọn. Rất có thể bạn sẽ tìm thấy những điểm có thể tối ưu hóa để làm cho ứng dụng của mình hoạt động tốt hơn.

Để nâng cao kỹ năng, bạn có thể tìm hiểu thêm về các chủ đề nâng cao như lập chỉ mục (indexing), tối ưu hóa truy vấn và cấu trúc lưu trữ của InnoDB. Chúc bạn thành công trên con đường chinh phục MySQL

Đánh giá