MySQL索引比存储的数据大

时间:2011-04-19 08:03:00

标签: mysql database optimization indexing innodb

我有一个包含以下统计数据的数据库

Tables     Data   Index   Total
11     579,6 MB  0,9 GB  1,5 GB

因此,您可以看到指数接近2倍。并且有一个表约有700万行,占据了至少99%。

我还有两个非常相似的索引

a) UNIQUE KEY `idx_customer_invoice` (`customer_id`,`invoice_no`),
b) KEY `idx_customer_invoice_order` (`customer_id`,`invoice_no`,`order_no`)

更新:这是最大表的表定义(至少在结构上)

CREATE TABLE `invoices` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `customer_id` int(10) unsigned NOT NULL,
  `order_no` varchar(10) default NULL,
  `invoice_no` varchar(20) default NULL,
  `customer_no` varchar(20) default NULL,
  `name` varchar(45) NOT NULL default '',
  `archived` tinyint(4) default NULL,
  `invoiced` tinyint(4) default NULL,
  `time` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
  `group` int(11) default NULL,
  `customer_group` int(11) default NULL,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `idx_customer_invoice` (`customer_id`,`invoice_no`),
  KEY `idx_time` (`time`),
  KEY `idx_order` (`order_no`),
  KEY `idx_customer_invoice_order` (`customer_id`,`invoice_no`,`order_no`)
) ENGINE=InnoDB AUTO_INCREMENT=9146048 DEFAULT CHARSET=latin1 |

更新2

mysql> show indexes from invoices;
+----------+------------+----------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table    | Non_unique | Key_name                   | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+----------+------------+----------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| invoices |          0 | PRIMARY                    |            1 | id          | A         |     7578066 |     NULL | NULL   |      | BTREE      |         |
| invoices |          0 | idx_customer_invoice       |            1 | customer_id | A         |          17 |     NULL | NULL   |      | BTREE      |         |
| invoices |          0 | idx_customer_invoice       |            2 | invoice_no  | A         |     7578066 |     NULL | NULL   | YES  | BTREE      |         |
| invoices |          1 | idx_time                   |            1 | time        | A         |      541290 |     NULL | NULL   |      | BTREE      |         |
| invoices |          1 | idx_order                  |            1 | order_no    | A         |        6091 |     NULL | NULL   | YES  | BTREE      |         |
| invoices |          1 | idx_customer_invoice_order |            1 | customer_id | A         |          17 |     NULL | NULL   |      | BTREE      |         |
| invoices |          1 | idx_customer_invoice_order |            2 | invoice_no  | A         |     7578066 |     NULL | NULL   | YES  | BTREE      |         |
| invoices |          1 | idx_customer_invoice_order |            3 | order_no    | A         |     7578066 |     NULL | NULL   | YES  | BTREE      |         |
+----------+------------+----------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+

我的问题是:

  1. 有没有办法在MySQL中找到未使用的索引?
  2. 是否存在影响索引大小的常见错误?
  3. 可以安全地删除indexA吗?
  4. 如何衡量每个指数的大小?我得到的只是所有索引的总和。

5 个答案:

答案 0 :(得分:10)

您可以删除索引A,因为正如您所指出的,它是另一个索引的子集。并且可以在不中断正常处理的情况下执行此操作。

索引文件的大​​小本身并不令人担忧,而且净利益很可能很容易实现。换句话说,索引的有用性和价值不应该打折扣,因为它会产生一个大文件。

索引设计是一项复杂而微妙的技术,涉及对查询优化器解释和广泛测试的深入理解。但是一个常见的错误是在索引中包含太少的字段以使其变小。另一种方法是测试索引数据不足或代表性不足。

答案 1 :(得分:6)

我可能错了,但是第一个索引(idx_customer_invoice)是UNIQUE,第二个(idx_customer_invoice_order)不是,所以当你删除它时你可能会失去唯一性约束。否?

答案 2 :(得分:1)

  

有没有办法在MySQL中找到未使用的索引?

在尝试优化查询时,数据库引擎优化器将选择适当的索引。根据您最后收集索引统计信息的时间,所选的索引会有所不同。由于新的数据重新分区,未使用的索引可能会突然被使用。

  

可以安全删除indexA吗?

如果indexA和indexB是B-Tree索引,我会说是的。这是因为以相同顺序以相同列开头的索引将具有相同的结构。

答案 3 :(得分:1)

使用

show indexes from table;

定义特定表中的索引。基数会告诉您索引的有用性。

您可以安全地删除索引(它不会破坏表),但要注意:某些查询执行速度可能较慢。首先,您应该分析您的查询,以决定是否需要某个索引。

但我认为你不能找到特定索引的数据长度。

但是,我认为您可能认为如果索引长度大于数据长度两次是异常的......那么,你错了。所有索引都可能有用;)如果你有一个提供大量信息的表,你必须在大量的列上搜索它,很容易就是这个表的索引的大小要大2倍表数据。

答案 4 :(得分:0)

  1. indexA可以删除,因为有一个 indexB包括indexA
  2. 您的索引长度会受到什么影响 您的列类型和列长
  3. 使用:

    从information_schema.tables中选择index_length             table_name ='your_table_name'和 TABLE_SCHEMA = 'your_db_name';

    获取你的表index_length