如何向MySQL表添加索引?

Mic*_*ael 395 mysql indexing optimization row

我有一个非常大的MySQL表,大约有150,000行数据.目前,当我尝试并运行时

SELECT * FROM table WHERE id = '1';
Run Code Online (Sandbox Code Playgroud)

代码运行正常,因为ID字段是主索引.但是,最近对于项目的开发,我必须通过另一个字段搜索数据库.例如

SELECT * FROM table WHERE product_id = '1';
Run Code Online (Sandbox Code Playgroud)

此字段以前没有编入索引,但是,我已将其添加为索引,但是当我尝试运行上述查询时,结果非常慢.EXPLAIN查询显示,当我已经添加了一个索引时,product_id字段没有索引,因此查询从20分钟到30分钟的任何位置返回单行.

我的完整EXPLAIN结果是:

| id | select_type | table | type | possible_keys| key  | key_len | ref  | rows  | Extra       |
+----+-------------+-------+------+--------------+------+---------+------+-------+------------------+
|  1 | SIMPLE      | table | ALL  | NULL         | NULL | NULL    | NULL |157211 | Using where |
+----+-------------+-------+------+--------------+------+---------+------+-------+------------------+
Run Code Online (Sandbox Code Playgroud)

注意我刚看了一眼,ID字段存储为INT,而PRODUCT_ID字段存储为VARCHAR,这可能会有所帮助.这可能是问题的根源吗?

zer*_*kms 585

ALTER TABLE `table` ADD INDEX `product_id` (`product_id`)
Run Code Online (Sandbox Code Playgroud)

永远不要比较integer,以strings在MySQL.如果idint,删除引号.

  • 使用`SHOW INDEXES FROM YOURTABLE` http://dev.mysql.com/doc/refman/5.0/en/show-index.html检查索引是否已添加 (32认同)
  • 今天我遇到了@Michael描述的确切问题,解决方案是"永远不要将整数与mysql中的字符串进行比较".谢谢. (5认同)

小智 147

ALTER TABLE TABLE_NAME ADD INDEX (COLUMN_NAME);
Run Code Online (Sandbox Code Playgroud)

  • 在MySQL中,如果使用`ALTER TABLE tbl ADD INDEX(col)`而不是`ALTER TABLE tbl ADD INDEX col(col)`,那么不止一次使用`ALTER TABLE tbl ADD INDEX(col)`将继续添加名为`col_2`,`col_3`,......每一次.而使用`ALTER TABLE tbl ADD INDEX col(col)`第二次,将给出'ERROR 1061(42000):重复键名'col'. (94认同)

Hie*_* Vo 78

您可以使用此语法添加索引并控制索引的类型(HASH或BTREE).

create index your_index_name on your_table_name(your_column_name) using HASH;
or
create index your_index_name on your_table_name(your_column_name) using BTREE;
Run Code Online (Sandbox Code Playgroud)

您可以在此处了解BTREE和HASH索引之间的差异:http: //dev.mysql.com/doc/refman/5.5/en/index-btree-hash.html

  • 如果我没有指定,Hash 和 BTree 的默认值是什么? (2认同)
  • @RNKushwaha因为InnoDB和MyIsam不支持HASH,AFAIK,只有Memory和NDB存储引擎支持它 (2认同)

Ant*_*ony 59

值得注意的是,多个字段索引可以显着提高您的查询性能.因此,在上面的示例中,我们假设ProductID是唯一要查找的字段,但是查询说ProductID = 1 AND Category = 7然后多列索引有帮助.这是通过以下方式实现的:

ALTER TABLE `table` ADD INDEX `index_name` (`col1`,`col2`)
Run Code Online (Sandbox Code Playgroud)

此外,索引应与查询字段的顺序匹配.在我的扩展示例中,索引应该是(ProductID,Category),而不是相反.

  • 很好,显式命名索引可以轻松逆转。 (2认同)

Jaz*_*zzz 50

可以添加两种类型的索引:当您定义主键时,MySQL默认将其作为索引.

说明

主键作为索引

考虑你有一个tbl_student表,你想要student_id作为主键:

ALTER TABLE `tbl_student` ADD PRIMARY KEY (`student_id`)
Run Code Online (Sandbox Code Playgroud)

上面的语句添加了一个主键,这意味着索引值必须是唯一的,不能为NULL.

指定索引名称

ALTER TABLE `tbl_student` ADD INDEX student_index (`student_id`)
Run Code Online (Sandbox Code Playgroud)

上面的语句将创建一个student_index名称的普通索引.

创建唯一索引

ALTER TABLE `tbl_student` ADD UNIQUE student_unique_index (`student_id`)
Run Code Online (Sandbox Code Playgroud)

这里,student_unique_index是分配给student_id的索引名称,并创建一个索引,其值必须是唯一的(此处为null可以接受).

全文选项

ALTER TABLE `tbl_student` ADD FULLTEXT student_fulltext_index (`student_id`)
Run Code Online (Sandbox Code Playgroud)

上面的语句将创建全文索引名称student_fulltext_index,您需要MyISAM Mysql Engine.

如何删除索引?

DROP INDEX `student_index` ON `tbl_student`
Run Code Online (Sandbox Code Playgroud)

如何查看可用的索引?

SHOW INDEX FROM `tbl_student`
Run Code Online (Sandbox Code Playgroud)


Wri*_*ken 17

你说你有一个索引,解释说不然.但是,如果你真的这样做,这就是如何继续:

如果列上有索引,并且MySQL决定不使用它,那可能是因为:

  1. 在MySQL认为更适合使用的查询中有另一个索引,它只能使用一个.如果它们的常规检索方法的值超过一列,则解决方案通常是跨越多列的索引.
  2. MySQL决定有许多匹配的行,并认为tablescan可能更快.如果不是这样,有时候会有所ANALYZE TABLE帮助.
  3. 在更复杂的查询中,它决定不在查询计划中基于非常智能的深思熟虑的巫术使用它,由于某种原因,它不符合您当前的要求.

在(2)或(3)的情况下,您可以通过索引提示sytax来哄骗MySQL使用索引,但是如果这样做,请确保运行一些测试以确定它是否实际上提高了使用索引的性能,因为您提示它.