是否有一个公式来估算InnoDB中的索引大小?

时间:2016-07-07 14:42:33

标签: mysql innodb rdbms

如何计算InnoDB中特定列类型的索引大小,即:

  • VARCHAR
  • CHAR
  • 时间戳
  • SMALLINT

我找到了MyISAM的公式(http://dev.mysql.com/doc/refman/5.7/en/key-space.html):( key_length + 4)/0.67

这对InnoDB也有效吗?

我正在尝试估算我正在设计用于调整大小的数据库的大小。

2 个答案:

答案 0 :(得分:4)

在InnoDB中,PRIMARY KEY嵌入了数据,因此您可以将其视为不占用空间。

对于辅助密钥...采用MyISAM公式,但包括的列次要密钥和PRIMARY KEY。然后乘以3.(有很多开销。)不过,在任何一个方向上答案都可以减少2倍。

请注意,如果你有很多辅助密钥,那么PK的大小会对表+索引的整体空间产生很大的影响。

示例

SET @db = 'world', @tbl = 'cities';
    SELECT      n_rows AS 'Approx Rows',
                'Data & PK' AS 'Type',
                clustered_index_size * 16384 AS Bytes,
                ROUND(clustered_index_size * 16384 / n_rows) AS 'Bytes/row',
                clustered_index_size AS Pages,
                ROUND(n_rows / clustered_index_size) AS 'Rows/page'
        FROM mysql.innodb_table_stats
        WHERE database_name = @db
          AND table_name = @tbl
    UNION
        SELECT  n_rows,
                'Secondary Indexes' AS 'BTrees',
                sum_of_other_index_sizes * 16384 AS Bytes,
                ROUND(sum_of_other_index_sizes * 16384 / n_rows) AS 'Bytes/row',
                sum_of_other_index_sizes AS Pages,
                ROUND(n_rows / sum_of_other_index_sizes) AS 'Rows/page'
        FROM mysql.innodb_table_stats
        WHERE database_name = @db
          AND table_name = @tbl
          AND sum_of_other_index_sizes > 0
          ;
-- (Percona has a different way.)

输出:

+-------------+-------------------+-----------+-----------+-------+-----------+
| Approx Rows | Type              | Bytes     | Bytes/row | Pages | Rows/page |
+-------------+-------------------+-----------+-----------+-------+-----------+
|     2637973 | Data & PK         | 179077120 |        68 | 10930 |       241 |
|     2637973 | Secondary Indexes | 232341504 |        88 | 14181 |       186 |
+-------------+-------------------+-----------+-----------+-------+-----------+

该表有两个索引:

PRIMARY KEY(...)  -- 14 bytes
INDEX(state, population)
INDEX(state, city)
  state CHAR(2) CHARACTER SET ascii -- 2 bytes
  population INT UNSIGNED -- 4 bytes
  city  -- AVG(LENGTH(city)) = 1+9.07 bytes

COUNT(*): 2,699,354  (the InnoDB estimate was not too far from this)

First index:  20    bytes * 2.7M rows = 54MB
Second index: 26.07 bytes * 2.7M rows = 70MB
Total:  124MB
Actual: 232MB
Ratio: 1.9x  (note: I skipped the "/0.67")

为了证明另一点,我尝试了OPTIMIZE TABLE。之后的统计数据基本相同:

+-------------+-------------------+-----------+-----------+-------+-----------+
| Approx Rows | Type              | Bytes     | Bytes/row | Pages | Rows/page |
+-------------+-------------------+-----------+-----------+-------+-----------+
|     2685828 | Data & PK         | 179077120 |        67 | 10930 |       246 |
|     2685828 | Secondary Indexes | 232341504 |        87 | 14181 |       189 |
+-------------+-------------------+-----------+-----------+-------+-----------+

答案 1 :(得分:2)

一个辅助索引记录是索引字段+主键。总结字段大小,乘以记录数,增加一些开销,这将是索引大小。