MySQL Data Types
Every MySQL data type with its storage size, range and the practical notes: integers, DECIMAL for money, VARCHAR and TEXT limits, DATETIME versus TIMESTAMP and the 2038 problem, JSON and VECTOR.
Free · No sign-up · Your inputs stay in your browser
Reference
MySQL data types
| Type | Storage | Range and notes |
|---|---|---|
| TINYINT | 1 byte | -128 to 127, or 0 to 255 UNSIGNED. BOOLEAN is an alias for TINYINT(1). |
| SMALLINT | 2 bytes | -32,768 to 32,767, or 0 to 65,535 UNSIGNED. |
| MEDIUMINT | 3 bytes | -8,388,608 to 8,388,607, or 0 to 16,777,215 UNSIGNED. |
| INT | 4 bytes | -2,147,483,648 to 2,147,483,647, or up to 4,294,967,295 UNSIGNED. The (11) display width is deprecated and ignored. |
| BIGINT | 8 bytes | ±9.2 × 10^18, or up to 1.8 × 10^19 UNSIGNED. Laravel's id() is BIGINT UNSIGNED. |
| DECIMAL(M,D) | about 4 bytes per 9 digits | Exact. Up to 65 digits. Use for money: DECIMAL(19,4) or integer cents. |
| FLOAT / DOUBLE | 4 / 8 bytes | Approximate binary floating point; never for money. |
| BIT(M) | (M+7)/8 bytes | 1 to 64 bits. |
| CHAR(N) | N × max bytes per char | Fixed length, padded; N up to 255 characters. |
| VARCHAR(N) | length + 1 or 2 bytes | N in characters; the whole row is limited to 65,535 bytes. With utf8mb4 an indexed VARCHAR(255) uses up to 1,020 bytes. |
| TINYTEXT / TEXT / MEDIUMTEXT / LONGTEXT | +1 / 2 / 3 / 4 bytes | Up to 255 B, 64 KiB, 16 MiB, 4 GiB. Cannot have a default before MySQL 8.0.13; indexes need a prefix length. |
| BINARY(N) / VARBINARY(N) | like CHAR / VARCHAR | Bytes, compared byte by byte. BINARY(16) stores a UUID in 16 bytes. |
| TINYBLOB ... LONGBLOB | as the TEXT types | Binary data; usually better kept in object storage. |
| DATE | 3 bytes | 1000-01-01 to 9999-12-31. |
| DATETIME(fsp) | 5 bytes + fractional | 1000-01-01 to 9999-12-31 23:59:59, no time zone. fsp 0-6 for fractions of a second. |
| TIMESTAMP(fsp) | 4 bytes + fractional | 1970-01-01 00:00:01 to 2038-01-19 03:14:07 UTC, stored in UTC and converted to the session time zone. The 2038 limit is real. |
| TIME(fsp) | 3 bytes + fractional | -838:59:59 to 838:59:59: a duration as much as a time of day. |
| YEAR | 1 byte | 1901 to 2155. |
| JSON | like LONGBLOB | Validated and stored in a binary format; index a field through a generated column or a functional index. |
| ENUM('a','b') | 1 or 2 bytes | Up to 65,535 values; adding one at the end is cheap, reordering rewrites the table. |
| SET('a','b') | 1 to 8 bytes | Up to 64 members, several at once. |
| GEOMETRY / POINT | variable | Spatial types with SPATIAL indexes; POINT with SRID 4326 for latitude and longitude. |
| VECTOR(N) | 4 × N bytes | MySQL 9.0+: N single-precision floats for embeddings. |
For MySQL 8.0 and 8.4 LTS with InnoDB; MariaDB matches for everything but JSON (an alias of LONGTEXT there) and VECTOR. Choose the smallest type that fits for good reason: every secondary index repeats the primary key, so a BIGINT key costs 4 bytes more in every index than an INT one.
About this tool
Method, assumptions, practical next steps, and limits.
Choices that matter later
TIMESTAMP stores UTC and converts to the session time zone, but ends on 19 January 2038; DATETIME has no zone and lasts until 9999. DECIMAL is exact and FLOAT is not, so money belongs in DECIMAL or integer cents. The INT(11) display width is deprecated and means nothing. The data type storage requirements page is the reference.
Smaller keys, smaller indexes
In InnoDB every secondary index stores the primary key, so a key type four bytes larger costs four bytes in every index entry. Choose BIGINT where you need its range, not by default everywhere.