MySQL索引:它们如何工作?

bob*_*yer 3 mysql indexing

我是MySQL索引的全新手.我在MySQL 5.0x上有几个MyISAM表,其中utf8字符集和排序规则各有100k +记录.主键通常是整数.每个表上的许多列可能具有重复值.

我需要快速计算,求和,平均或以其他方式对每个表中的任意数量的字段执行自定义计算,或者加入任意数量的其他字段.

我发现这个页面概述了MySQL索引的用法:http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html,但我仍然不确定我是否正确使用索引.就在我认为我已经从我想要计算的字段集合中创建完美索引时,我得到"索引必须低于1000字节"错误.

任何人都可以解释如何最有效地创建和使用索引来加速查询?

警告:在这种情况下升级Mysql是不可能的.使用Navicat Light进行数据库管理,但不需要此应用程序.

fut*_*eal 8

当您在MySQL表中的一列或多列上创建索引时,数据库正在创建一个称为B树的数据结构(假设您使用默认索引设置),每个记录的键是一个值的串联.索引列.

例如,假设您有一个表定义如下:

CREATE TABLE mytable (
 id int unsigned auto_increment,
 column_a char(32) not null default '',
 column_b int unsigned not null default 0,
 column_c varchar(512),
 column_d varchar(512),
 PRIMARY KEY (id)
) ENGINE=MyISAM;
Run Code Online (Sandbox Code Playgroud)

然后让我们给它一些数据:

INSERT INTO mytable VALUES (1, 'hello', 2, null, null);
INSERT INTO mytable VALUES (2, 'hello', 3, 'hi', 'there');
INSERT INTO mytable VALUES (3, 'how', 4, 'are', 'you?');
INSERT INTO mytable VALUES (4, 'foo', 5, '', 'bar');
Run Code Online (Sandbox Code Playgroud)

现在假设你决定添加一个键,column_a并且column_b喜欢:

ALTER TABLE mytable ADD KEY (column_a, column_b);
Run Code Online (Sandbox Code Playgroud)

数据库将创建上述B树,其中包含四个键,每行一个:

hello-2
hello-3
how-4
foo-5
Run Code Online (Sandbox Code Playgroud)

当您执行引用该column_a列的搜索或引用column_aAND column_b列的搜索时,数据库将能够使用此索引来缩小它必须检查的记录集.假设您有一个类似的查询:

SELECT ... FROM mytable WHERE column_a = 'hello';
Run Code Online (Sandbox Code Playgroud)

即使上面的查询没有为column_b列指定值,它仍然可以通过查找以"hello"开头的所有键来利用我们的索引.出于同样的原因,如果你有一个像这样的查询:

SELECT ... FROM mytable WHERE column_b = '2';
Run Code Online (Sandbox Code Playgroud)

此查询将无法使用我们的索引,因为它必须解析索引键本身以尝试确定哪些键的第二个值匹配'2',这非常低效.

现在,让我们解决您最大长度的原始问题.假设我们尝试创建一个跨越此表中所有四个非PK列的索引:

ALTER TABLE mytable ADD KEY (column_a, column_b, column_c, column_d);
Run Code Online (Sandbox Code Playgroud)

你会收到一个错误:

ERROR 1071 (42000): Specified key was too long; max key length is 1000 bytes
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我们的列长度为32,10,512和512,在每个字符的单字节情况下为1066,高于1000的限制.假设它的DID工作; 您将创建以下键:

hello-2-
hello-3-hi-there
how-4-are-you?
foo-5--bar
Run Code Online (Sandbox Code Playgroud)

现在,假设您有值column_ccolumn_d非常长 - 每个512个字符.即使在基本的单字节字符集中,您的密钥现在也将超过1000个字节,这正是MySQL所抱怨的.使用多字节字符集会更糟糕,其中看似"小"的列仍然可以将键推到限制之上.

如果你必须使用一个大的复合键,一个解决方案是使用InnoDB表而不是默认的MyISAM表,它支持更大的密钥长度(3500字节) - 你可以通过交换ENGINE=InnoDB而不是ENGINE=MyISAM在上面的声明中来做到这一点.但是,一般来说,如果您使用长按键,则表格设计可能存在问题.

请记住,单列索引通常比多列索引提供更多实用程序.当您经常/通过在查询中指定所有必要条件时,您希望使用多列索引.此外,正如其他人所提到的,不要索引表的每一列,因为每个索引都会为数据库添加存储开销.您希望将索引限制为查询经常使用的列,如果您需要太多,则应该考虑将表分解为更多逻辑组件.