我有一个 MyISAM 表 T,其架构如下:
f1 (无符号非空整数) f2 (无符号非空整数)
该表在 f2 上有索引,目前包含 3.2 亿行,预计每周以约 20 万行的速度增长。我在该表上执行以下查询:
从 T 中选择不同的 T.f1,其中 f2=@Var LIMIT ?,30
@Var 是传递给执行此查询的存储过程的变量,LIMIT 变量根据显示的页码而变化(从 0 开始,等等)
检索速度非常快(考虑到表非常大),但行按写入表的顺序显示(即不是按 f1 顺序)。我希望能够在上面的查询中包含子句“ORDER BY f1 DESC”,但是,如果没有 INDEX 这样做会适得其反!(有时可能有超过一百万行满足查询,而没有索引对它们进行排序可能会杀死服务器)
我的问题是...应该存在哪些索引来满足我正在运行的查询以及结果中行的排序?如果使用索引无法满足查询和排序,我考虑在更新后执行 ALTER TABLE T ORDER BY f1 DESC(此时用户仍然可以查询数据)。在这种情况下,在我的开发机器上,alter 语句大约需要 50 分钟,这还不算太糟糕。显然,在 LIVE 机器上,我需要拥有与原始表大小一样多的磁盘可用空间...还有其他需要考虑的吗?
提前致谢,蒂姆
答案1
我不确定你关于 ORDER BY 子句需要 f1 上的索引的假设是否正确。我创建了这样一个表并运行
解释 SELECT DISTINCT T.f1 作为结果 FROM rowtest T WHERE f2=10 按结果排序 LIMIT 0,30
我得到了这个:
id | select_type | 表 | 类型 | 可能键 | 键 | 键长度 | ref | 行 | 额外的 1 | SIMPLE | T | ref | idx_f2 | idx_f2 | 4 | const | 3 | 使用 where;使用 temporary;使用 filesort
现在,服务器将使用临时表和文件排序这一事实并不意味着这是一种特别快速或有效的方法。但是,其中没有任何内容表明您需要在 f1 上建立索引。忽略这样一个事实:在我的例子中,结果集中只有 3 行(我无法承受创建一个包含 3.2 亿行的表)。
现在:如果我在表的 f1 列上添加一个索引,解释的结果根本不会改变,这意味着您是否有索引并不重要。
原因在于,服务器首先检索满足 where 条件的所有行(使用 f2 上的索引),然后使用临时文件对它们进行排序。在检索行期间,f1 上的索引毫无用处,而在排序阶段,它不存在。
考虑到您的结果集永远不会超过 30 行,临时文件中的排序根本不会占用任何时间。亲自尝试一下。
编辑忘记最后那句话,那是胡说八道。我刚刚意识到 LIMIT 子句被应用了后排序开始。所以:是的,排序需要一些时间。但是,如果您的查询实际上只返回一个数字列,它应该会非常快。还有一个事实:f1 上的索引没有任何区别。另外:据我所知,一旦检索了所有行,表就不会被锁定以进行任何其他访问。而且因为这不会改变,所以无论您是否使用 ORDER BY 子句,都不会对其他用户产生影响。