4

我有一个包含数百万个条目的表,以及一个具有BIGINT(20)每行唯一值的列。它们不是主键,但在某些操作过程中,子句 中有数千个SELECT使用该列。WHERE

问:当条目数量增长到数百万时,向该列添加索引会有所帮助吗?我知道它适用于文本值,但我不熟悉索引对INTor的作用BIGINT

SELECT一个会发生数千次的样本与此类似:

`SELECT * FROM table1 WHERE my_big_number=19287319283784
4

3 回答 3

6

如果您有一个非常大的表,那么搜索未编入索引的值可能会非常慢。在 MySQL 术语中,这种查询最终成为“表扫描”,这是一种说法,它必须按顺序对表中的每一行进行测试。这显然不是最好的方法。

添加索引将有助于提高读取速度,但您付出的代价是写入速度稍慢。进行优化时总是需要权衡取舍,但在您的情况下,读取时间的减少将是巨大的,而写入时间的增加将是微不足道的。

请记住,将索引添加到大表可能需要相当长的时间,因此在将其应用于生产系统之前,请针对生产数据进行测试。该表可能会在ALTER TABLE语句期间被锁定。

与往常一样,使用EXPLAIN您的查询来确定它们的执行策略。在你的情况下,它会是这样的:

EXPLAIN SELECT * FROM table1 WHERE my_big_number=19287319283784
于 2012-11-13T20:02:43.677 回答
1

它将提高您的查找 (SELECT) 性能(基于您的示例查询),但它也会使您的插入/更新速度变慢。您的数据库大小也会增加。您需要查看进行这些 SELECT 调用与 INSERT 调用的频率。如果您进行了很多 SELECT 调用,那么这应该会提高您的整体性能。

于 2012-11-13T19:59:51.007 回答
1

我在亚马逊 ec2 小实例上有一个 2200 万行的表。因此,它绝对不是最快的服务器环境。我有这个创建:

CREATE TABLE huge
(
    myid int not null AUTO_INCREMENT PRIMARY KEY,
    version int not null,
    mykey char(40) not null,
    myvalue char(40) not null,
    productid int not null
);

CREATE INDEX prod_ver_index ON huge(productid,version);

此调用运行立即结束:

select * from huge where productid=3333 and version=1988210878;

至于inserts,我可以在 PHP 中执行 100/秒,但如果我将 1000 次插入塞入数组中,则在同一张表上使用 implode,我每秒得到 3400 次插入。自然,您的数据不会以这种方式出现。只是说服务器相对活泼。但正如 tadman 所建议的那样,他的意思是EXPLAIN不要检查,在一个典型的语句前面,看看键列是否显示了一个索引,如果你运行它,它将被使用。

普通的留言

对于慢查询调试,将单词放在单词EXPLAIN前面select(无论多么复杂) ,select/join然后运行它。尽管在解析结果集时查询不会以正常方式运行,但数据库引擎将(几乎立即)生成它将尝试的执行计划。当真正的查询运行时(将 EXPLAIN 放在它前面的那个),这个计划可能会被放弃,但它是模式缺陷的主要线索。

对于那些第一次阅读的人来说,输出EXPLAIN似乎很神秘。不过时间不长。在阅读了几篇关于它的文章后,例如Using EXPLAIN to Write Better MySQL Queries,通常能够确定查询的哪些部分正在使用哪些索引,不使用并执行慢速表扫描,较慢的 where 子句,派生表和临时表.

使用针对您的架构调整大小的 EXPLAIN 的输出,您可以深入了解索引创建(例如compositecovering索引)的策略,从而获得可观的查询性能。

分享

与其他人共享此EXPLAIN输出和模式输出(例如在 stackoverflow 问题中)可以加快有关性能的更好答案。Schema 输出使用诸如show create table myTableName. 感谢你的分享。

于 2012-11-13T20:26:38.063 回答