Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

Database Table Size Calculator (PostgreSQL & MySQL)

How much disk a table will take, now and after a year, from its columns and rows.

Free preview, no sign-upIncluded in your pass Pro tool Pro pass: ₹179 / $5.99 for 30 days On this device: nothing is sent
+3 +1 more details No uploadWorks offline once opened Developer

Free preview: the total size now in full, with the first rows of each table (up to 3) and the first step of the working; every other figure is hidden. Locked until you unlock it: download and copy.

Pro pass ₹179 for 30 days or ₹79 for 1 week, one‑time. Pro pass $5.99 for 30 days or $2.99 for 1 week, one‑time. How to unlock

Try before you buy.

  • Free preview: the total size now in full, with the first rows of each table (up to 3) and the first step of the working; every other figure is hidden.
  • Locked until you unlock it: download and copy.
  • Unlock: Pro pass, ₹179 for 30 days or ₹79 for 1 week, a one-time payment that never renews. Unlock: Pro pass, $5.99 for 30 days or $2.99 for 1 week, a one-time payment that never renews.

Ways to unlock shows how to get the full result.

See passes (opens in a new tab)

Printing this result is locked in the free preview.

Database
Paste CREATE TABLE
Columns

For text, varchar, JSON and binary columns enter the average size of a value in bytes; empty uses an assumed size. NULL % is the share of rows where a nullable column is empty.

    Keys and indexes
    Comma-separated, in key order. Empty: no primary key.
      Rows and growth

      Next steps Done. What next?

      Start over

      A Pro pass unlocks the full result. See passes

      All developer tools

      About the Database Table Size Calculator (PostgreSQL & MySQL)

      Estimate the disk a table will need before you create it. Enter its columns and types — or paste its CREATE TABLE and CREATE INDEX statements — with the expected rows, the monthly growth and the indexes, and get the size of the table, of its long values and of each index, now and over three years.

      The estimate follows how the databases lay rows out on disk. For PostgreSQL: 8 kB pages, a 23-byte header on every row, a null bitmap when the row has NULLs, padding so each column starts on its alignment boundary, a 4-byte line pointer per row, the table’s fillfactor, and TOAST, which compresses and moves values out of rows longer than 2,032 bytes. For MySQL and MariaDB (InnoDB): 16 kB pages filled to 15/16, a 5-byte record header, the NULL bitmap and length bytes, the 13 bytes of transaction id and roll pointer every row carries, secondary indexes that store the primary key, and long values moved off-page. The working is shown step by step, and for PostgreSQL the calculator suggests the column order that wastes the least padding.

      Without a pass the page shows a free preview: the total size now in full, the first rows of each table and the first step of the working; the other figures, the copy and the CSV unlock with a Pro pass. Everything is worked out in your browser.

      How to use it

      1. Choose PostgreSQL or MySQL / MariaDB.
      2. Enter the columns with their types, or open “Paste CREATE TABLE”, paste the statements and press “Read the statement”. Columns, the primary key and the indexes are filled in.
      3. For variable-length columns (text, varchar, JSON, bytea) enter the average size in bytes, and for nullable ones the share of rows that are NULL. Without them the calculator assumes a size and says so.
      4. Enter the expected rows and the monthly growth (rows a month or a percentage), and whether new keys arrive in order (serial, timestamps) or at random (UUID v4).
      5. Read the total, the size after a year and the breakdown. Copying the summary and the CSV of the projection needs a pass; the free preview shows the first rows. After you create the table, run the check query to compare with the real sizes.

      Examples

      One integer column, a million rows (PostgreSQL)
      Input
      CREATE TABLE t (i integer NOT NULL); 1,000,000 rows
      Result
      226 rows per 8 kB page → 4,425 pages = 34.6 MB

      Each row is a 23-byte header padded to 24, 4 bytes of data, padded to 32, plus a 4-byte line pointer: 8,168 ÷ 36 = 226 rows a page.

      The same table with a primary key
      Input
      i integer PRIMARY KEY; 1,000,000 rows
      Result
      Index: 20-byte entries, 365 a leaf page → 2,740 leaf pages + 12 others = 21.5 MB

      An index entry is an 8-byte header, the 4-byte key padded to 16, and a line pointer; leaf pages are filled to the default fillfactor of 90%.

      Column order and padding
      Input
      a boolean, b bigint, c boolean, d integer
      Result
      10 bytes of padding a row; ordered b, d, a, c: 8 bytes less per row

      bigint starts on an 8-byte boundary and integer on a 4-byte one, so a 1-byte boolean before each wastes 7 and 3 bytes.

      An InnoDB table (MySQL)
      Input
      id INT PRIMARY KEY, name VARCHAR(100) averaging 20 bytes; 1,000,000 rows
      Result
      43-byte records, 351 a page → 2,854 pages = 44.6 MB

      5 (record header) + 13 (transaction id and roll pointer) + 4 (id) + 20 + 1 (length byte); pages are filled to 15/16 when ids arrive in order.

      Common uses

      • Size the disk or the cloud volume for a new service before it launches.
      • Compare UUID and bigint keys, or narrower column types, by the space they cost.
      • Find the column order that saves padding on a wide PostgreSQL table.
      • Plan when a growing table will outgrow its storage.

      How a PostgreSQL row is sized

      • Every row starts with a 23-byte header. When the row has a NULL, a bitmap of one bit per column follows. The header is padded to 8 bytes, so it is 24 bytes, or 32 with a bitmap of up to 72 columns.
      • Each column starts on its type’s alignment boundary: 8 bytes for bigint, double precision, timestamp and timestamptz, 4 for integer, date, real and long text, 2 for smallint, none for boolean, uuid and short text.
      • Text, varchar, bytea, numeric and JSON values of up to 126 bytes take a 1-byte header and no alignment; longer ones a 4-byte header. numeric takes 2 bytes per four digits plus 3 bytes.
      • The row is padded to a multiple of 8 and needs a 4-byte line pointer on its page. A page holds 8,168 bytes of rows at most (291 rows), less the share the fillfactor reserves for updates.
      • A row larger than 2,032 bytes is toasted: long values are compressed and, if still too large, moved to the TOAST table in chunks of 1,996 bytes, four to a page, leaving an 18-byte pointer in the row.
      • B-tree entries are an 8-byte header (16 with NULL keys) and the key, padded to 8, with a line pointer; leaf pages are filled to the index fillfactor (90 by default) and inner pages to 70%.

      How an InnoDB row is sized

      • Each record has a 5-byte header, a NULL bitmap of one bit per nullable column, and one or two length bytes per non-NULL variable-length value; NULL values take no other space.
      • Every row of the clustered index (the table) carries a 6-byte transaction id and a 7-byte roll pointer; without a primary key, InnoDB adds a 6-byte row id, unless a unique index on NOT NULL columns can take its place.
      • Types take the bytes the manual lists: INT 4, BIGINT 8, DATETIME 5 and TIMESTAMP 4 (plus up to 3 for fractional seconds), DECIMAL 4 bytes per nine digits, VARCHAR the value plus its length bytes; with a multi-byte character set CHAR(N) keeps at least N bytes.
      • Pages are 16 kB with 128 bytes of headers and a 2-byte directory slot per 4 to 8 records. Inserts in key order fill pages to about 15/16; random keys leave them between half full and 15/16 full (the estimate uses about 72%).
      • Secondary index records hold the index columns and the primary key. A record longer than about half a page moves its longest TEXT, BLOB or long VARCHAR values off-page behind 20-byte pointers, each value in whole 16 kB pages.

      Checking the estimate against the real table

      Once the table exists and holds data, the check query shows what the database itself reports: in PostgreSQL pg_relation_size, pg_table_size (with TOAST), pg_indexes_size and pg_total_relation_size, and avg(pg_column_size(t.*)) for the real average row; in MySQL data_length and index_length from information_schema.tables after ANALYZE TABLE (these are estimates from statistics too). Measure your real average value sizes with avg(pg_column_size(column)) or AVG(LENGTH(column)) and enter them to tighten the estimate.

      Sources

      Limitations

      • These are estimates of a freshly loaded table. Updates and deletes leave dead rows and empty space behind (bloat in PostgreSQL, fragmentation in InnoDB) until VACUUM or OPTIMIZE TABLE reclaims them, so a busy table is usually larger.
      • Averages stand in for real values: rows of very different sizes, and how well long values compress, change the result. Enter measured averages where you can.
      • PostgreSQL B-tree deduplication (from version 13) shrinks indexes on repeated values; the estimate assumes distinct keys, so it is an upper bound for such indexes. GIN, GiST, BRIN and hash indexes are estimated as B-trees.
      • PostgreSQL’s space map and visibility map forks (a few pages each), InnoDB’s extent allocation and the redo and undo logs are not included.
      • User-defined types, domains and extension types are not known: enter the built-in type they are based on.

      Privacy

      On this device: nothing is sent

      Everything happens in your browser. What you enter or open here is not uploaded or stored by MySmartCoPilot.

      Frequently asked questions

      What do I get without a pass?

      Without a pass, Database Table Size Calculator (PostgreSQL & MySQL) shows the total size now in full, with the first rows of each table (up to 3) and the first step of the working; every other figure is hidden. Until you unlock it, the result can’t be downloaded or copied. A Pro, Premium or Ultimate pass, a one-time payment that never renews, unlocks the full result. The pricing page lists the passes and their prices.

      Why is a row bigger than the sum of its columns?

      Every PostgreSQL row has a 23-byte header (24 with padding) and a 4-byte line pointer, and columns are padded to their alignment, so a row of one integer takes 36 bytes of the page. InnoDB adds a 5-byte header and 13 bytes of transaction data to every row.

      Does the column order really change the size?

      In PostgreSQL, yes: each column starts on its alignment boundary, so a boolean before a bigint wastes 7 bytes of padding. Putting 8-byte columns first, then 4-, 2- and 1-byte ones, then the variable-length ones removes most of it. InnoDB does not pad columns, so the order does not matter there.

      What is TOAST and when does it apply?

      TOAST is how PostgreSQL stores large values. When a row is larger than 2,032 bytes (with 8 kB pages), PostgreSQL compresses its long values and moves them, if needed, to a separate TOAST table in chunks of 1,996 bytes, keeping an 18-byte pointer in the row.

      Why are UUID primary keys more expensive?

      A uuid takes 16 bytes against 8 for a bigint, in the table and in every index entry (in InnoDB every secondary index repeats the primary key). Random UUIDs also arrive out of order, so index pages split and settle around three-quarters full instead of 90% or 15/16.

      How close is the estimate to the real size?

      For PostgreSQL rows of fixed-width columns the calculation follows the page layout step by step, so the heap of a table loaded once is worked out as PostgreSQL lays it out. Variable-length values, NULLs, TOAST, indexes and InnoDB pages depend more on the real data and on the order rows arrive, so treat those parts as estimates. Run the check query on the real table and compare; enter measured averages for variable-length columns for the closest match.

      Quick answers and tool search

      Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.