SQL integer types are a family of fixed-width integer types differing in how many bytes each occupies and therefore in the range of values they can hold. In MySQL:
| Type | Bytes | Signed range | Unsigned range |
|---|---|---|---|
| TINYINT | 1 | to | to |
| SMALLINT | 2 | to | to |
| MEDIUMINT | 3 | to | to |
| INT | 4 | to | to |
| BIGINT | 8 | to |
Picking the right width matters for storage efficiency and, on very large tables, for performance — narrower types let more rows fit in a memory page, which makes scans faster. For a 10-million-row table, the choice between INT (4 bytes) and BIGINT (8 bytes) is 40 MB of difference for that column alone, plus whatever index space it occupies.
The general principle: pick the smallest type that comfortably accommodates the values the column will hold, plus future growth.
- TINYINT — boolean-like flags, percentages 0-100, small enumerations, ages.
- SMALLINT — counts up to ~30,000, IDs in small tables, years.
- INT — the workhorse. Most integer IDs, counts up to billions, financial amounts in cents up to ~$21 million.
- BIGINT — Unix timestamps in milliseconds, IDs in very large tables, financial amounts in cents above ~$21 million.
UNSIGNED doubles the positive range by sacrificing negative values. It’s appropriate when negative values are meaningless (counts, sizes, IDs that are never negative). Note that UNSIGNED is a MySQL extension — PostgreSQL has no unsigned integer types at all; SQL Server and SQLite likewise lack them. For portable code, either use the next-larger signed type (BIGINT instead of INT UNSIGNED) or add a CHECK (col >= 0) constraint.
MEDIUMINT is also MySQL-specific. PostgreSQL has only SMALLINT (2 bytes), INTEGER (4 bytes), and BIGINT (8 bytes). SQL Server adds TINYINT (1 byte, unsigned 0-255 only). SQLite’s INTEGER is variable-width up to 8 bytes regardless of how the column is declared.
For exact decimals (financial data), DECIMAL is the right type, not an integer. For approximate floating-point, FLOAT or DOUBLE. The integer family is for whole-number quantities only.
For primary keys, the standard idiom is INT NOT NULL AUTO_INCREMENT, sometimes BIGINT for tables expected to grow past a few billion rows.