我有一个包含数百万个条目的表,以及一个具有BIGINT(20)
每行唯一值的列。它们不是主键,但在某些操作过程中,子句 中有数千个SELECT
使用该列。WHERE
问:当条目数量增长到数百万时,向该列添加索引会有所帮助吗?我知道它适用于文本值,但我不熟悉索引对INT
or的作用BIGINT
。
SELECT
一个会发生数千次的样本与此类似:
`SELECT * FROM table1 WHERE my_big_number=19287319283784
我有一个包含数百万个条目的表,以及一个具有BIGINT(20)
每行唯一值的列。它们不是主键,但在某些操作过程中,子句 中有数千个SELECT
使用该列。WHERE
问:当条目数量增长到数百万时,向该列添加索引会有所帮助吗?我知道它适用于文本值,但我不熟悉索引对INT
or的作用BIGINT
。
SELECT
一个会发生数千次的样本与此类似:
`SELECT * FROM table1 WHERE my_big_number=19287319283784
如果您有一个非常大的表,那么搜索未编入索引的值可能会非常慢。在 MySQL 术语中,这种查询最终成为“表扫描”,这是一种说法,它必须按顺序对表中的每一行进行测试。这显然不是最好的方法。
添加索引将有助于提高读取速度,但您付出的代价是写入速度稍慢。进行优化时总是需要权衡取舍,但在您的情况下,读取时间的减少将是巨大的,而写入时间的增加将是微不足道的。
请记住,将索引添加到大表可能需要相当长的时间,因此在将其应用于生产系统之前,请针对生产数据进行测试。该表可能会在ALTER TABLE
语句期间被锁定。
与往常一样,使用EXPLAIN
您的查询来确定它们的执行策略。在你的情况下,它会是这样的:
EXPLAIN SELECT * FROM table1 WHERE my_big_number=19287319283784
它将提高您的查找 (SELECT) 性能(基于您的示例查询),但它也会使您的插入/更新速度变慢。您的数据库大小也会增加。您需要查看进行这些 SELECT 调用与 INSERT 调用的频率。如果您进行了很多 SELECT 调用,那么这应该会提高您的整体性能。
我在亚马逊 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 的输出,您可以深入了解索引创建(例如composite
和covering
索引)的策略,从而获得可观的查询性能。
与其他人共享此EXPLAIN
输出和模式输出(例如在 stackoverflow 问题中)可以加快有关性能的更好答案。Schema 输出使用诸如show create table myTableName
. 感谢你的分享。