如何向MySQL表添加索引?

时间:2010-06-09 01:41:24

标签: mysql optimization indexing row

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

SELECT * FROM table WHERE id = '1';

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

SELECT * FROM table WHERE product_id = '1';

此字段以前没有编入索引,但是,我已将其添加为索引,但是当我尝试运行上述查询时,结果非常慢。 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 |
+----+-------------+-------+------+----------------------+------+---------+------+------+------------------+

请注意,我刚看了一眼,ID字段存储为INT,而PRODUCT_ID字段存储为VARCHAR。这可能是问题的根源吗?

7 个答案:

答案 0 :(得分:561)

ALTER TABLE `table` ADD INDEX `product_id` (`product_id`)

永远不要在MySQL中将integerstrings进行比较。如果idint,请删除引号。

答案 1 :(得分:142)

ALTER TABLE TABLE_NAME ADD INDEX (COLUMN_NAME);

答案 2 :(得分:71)

您可以使用此语法添加索引并控制索引的类型(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;

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

答案 3 :(得分:51)

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

ALTER TABLE `table` ADD INDEX `index_name` (`col1`,`col2`)

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

答案 4 :(得分:44)

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

<强>解释

主键作为索引

考虑您有一个tbl_student表,并希望student_id作为主键:

ALTER TABLE `tbl_student` ADD PRIMARY KEY (`student_id`)

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

指定索引名称

ALTER TABLE `tbl_student` ADD INDEX student_index (`student_id`)

上述语句将创建一个名为student_index的普通索引。

创建唯一索引

ALTER TABLE `tbl_student` ADD UNIQUE student_unique_index (`student_id`)

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

全文选项

ALTER TABLE `tbl_student` ADD FULLTEXT student_fulltext_index (`student_id`)

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

如何删除索引?

DROP INDEX `student_index` ON `tbl_student`

如何查看可用索引?

SHOW INDEX FROM `tbl_student`

答案 5 :(得分:16)

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

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

  1. MySQL认为查询中有另一个索引更适合使用,它只能使用一个索引。如果它们的常规检索方法的值超过一列,那么解决方案通常是跨越多列的索引。
  2. MySQL决定有许多匹配的行,并认为tablescan可能更快。如果不是这种情况,有时ANALYZE TABLE有帮助。
  3. 在更复杂的查询中,它决定不在查询计划中基于非常智能的深思熟虑的巫术来使用它,因为某些原因它不符合您当前的要求。
  4. 在(2)或(3)的情况下,您可以哄骗MySQL使用index hint sytax索引,但是如果这样做,请确保运行一些测试以确定它是否确实提高了性能以使用你暗示它的索引。

答案 6 :(得分:1)

一个更好的选择是在CREATE TABLE查询期间直接添加约束(假设您具有有关表的信息)

CREATE TABLE products(
    productId INT AUTO_INCREMENT PRIMARY KEY,
    productName varchar(100) not null,
    categoryId INT NOT NULL,
    CONSTRAINT fk_category
    FOREIGN KEY (categoryId) 
    REFERENCES categories(categoryId)
        ON UPDATE CASCADE
        ON DELETE CASCADE
) ENGINE=INNODB;