如何向MySQL表添加索引?

如何向MySQL表添加索引?,mysql,optimization,indexing,row,Mysql,Optimization,Indexing,Row,我有一个非常大的MySQL表,大约有150000行数据。当前,当我尝试运行时 SELECT * FROM table WHERE id = '1'; 代码运行良好,因为ID字段是主索引。 然而,对于该项目的最新发展,我必须通过另一个字段搜索数据库。例如: SELECT * FROM table WHERE product_id = '1'; 此字段以前没有索引;但是,我添加了一个,所以mysql现在对字段进行索引,但是当我尝试运行上面的查询时,它运行得非常慢。EXPLAIN查询显示,当我已经

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

SELECT * FROM table WHERE id = '1';
代码运行良好,因为ID字段是主索引。 然而,对于该项目的最新发展,我必须通过另一个字段搜索数据库。例如:

SELECT * FROM table WHERE product_id = '1';
此字段以前没有索引;但是,我添加了一个,所以mysql现在对字段进行索引,但是当我尝试运行上面的查询时,它运行得非常慢。EXPLAIN查询显示,当我已经添加了product_id字段时,该字段没有索引,因此查询需要20分钟到30分钟的时间才能返回一行

我的全部解释结果如下:

| 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,这可能会有所帮助。这可能是问题的根源吗

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

永远不要将MySQL中的
整数
字符串
进行比较。如果
id
int
,请删除引号。

如果你说你有索引,解释会说没有。然而,如果你真的这样做了,这就是如何继续:

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

  • 在MySQL认为更适合使用的查询中还有另一个索引,它只能使用一个。如果通常的检索方法是按多个列的值进行检索,则解决方案通常是跨多个列的索引
  • MySQL决定有太多匹配的行,并认为tablescan可能更快。如果不是这样,有时一个
    分析表
    会有所帮助
  • 在更复杂的查询中,它决定不使用它,因为查询计划中的巫毒思想非常聪明,出于某种原因,它不适合您当前的需求

  • 在(2)或(3)的情况下,您可以通过诱使MySQL使用索引,但如果您这样做,请务必运行一些测试,以确定按照提示使用索引是否确实提高了性能。

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

    ALTER TABLE TABLE_NAME ADD INDEX (COLUMN_NAME);
    

    您可以在此处了解BTREE和哈希索引之间的差异:

    值得注意的是,多字段索引可以显著提高查询性能。因此,在上面的示例中,我们假设ProductID是唯一要查找的字段,但如果查询的ProductID=1和Category=7,则多列索引会有所帮助。这是通过以下方式实现的:

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

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

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

    解释

    ALTER TABLE `tbl_student` ADD FULLTEXT student_fulltext_index (`student_id`)
    
    主键作为索引

    ALTER TABLE `tbl_student` ADD UNIQUE student_unique_index (`student_id`)
    
    假设您有一个
    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\u index
    name

    创建唯一索引

    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\u Fulltext\u index
    创建全文索引名,您需要MyISAM Mysql引擎

    如何删除索引?

    DROP INDEX `student_index` ON `tbl_student`
    
    SHOW INDEX FROM `tbl_student`
    
    如何检查可用索引?

    DROP INDEX `student_index` ON `tbl_student`
    
    SHOW INDEX FROM `tbl_student`
    

    更好的选择是在CREATETABLE查询期间直接添加约束(假设您有关于表的信息)


    你能发布完整的
    解释
    结果吗?你确定没有索引吗?或者索引在那里,但MySQL选择不使用它?一个大表将有15000000条记录。一个非常大的表有1500000000条记录。平均大小的表有150000个。供将来参考。请注意“或”可以使MySql不使用索引。我问了3个或更多的问题。每台机器都有一个索引,运行时间为15毫秒,总共需要25秒到超时。所以我做了3个查询,把它们联合在一起,它也在500行上花费了15Ms。考虑你正在存储的数据类型。性能可能会根据正在比较的数据类型而变化。正如您所说,PRODUCT_ID是一个VARCHAR数据类型,请尝试将其更改为INT并为列编制索引。我已经使用该SQL添加了索引,但它似乎尚未“应用”到数据,解释查询显示该字段没有索引。请使用SHOW CREATE TABLE检查索引,或者您已经这样做了吗?使用
    从您的表中显示索引
    来检查索引是否已添加。今天,我遇到了@Michael所描述的确切问题,解决方案是“永远不要将整数与mysql中的字符串进行比较”。谢谢。@Wrikken我添加了我的索引,并使用了您的命令从您的表中显示索引。它出现了,但我认为在查询表时没有使用它。使用索引时我必须更改select查询吗?在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)
    时,将出现
    错误1061(42000):重复的键名“col”
    。当我看到使用show INDEX时,哈希转换为btree。如果我不指定任何值,哈希和btree的默认值是多少?@RNKushwaha,因为InnoDB和MyIsam不支持哈希,AFAIK,只有内存和NDB存储引擎支持itNice,显式命名索引允许轻松检索