我应该在一个页面中添加和删除索引吗?

时间:2010-09-10 23:23:44

标签: php mysql optimization

假设我有players表。它由3行组成(它有更多,但我们假设它只有3行)。 member_id, name, exp。我在每个页面使用member_id行,这就是为什么我只将索引添加到member_id。但是我希望在一个页面中列出最高exp的顶级玩家列表。所以我做了类似的事情:

$query = mysql_query("SELECT * FROM players ORDER BY `exp` DESC");

如果我有10k玩家,我无法在不向exp添加索引的情况下运行此类查询。所以我的问题是,我应该这样做:

mysql_query("ALTER TABLE `players` ADD INDEX ( `exp` )");
$query = mysql_query("SELECT * FROM players ORDER BY `exp` DESC");
mysql_query("ALTER TABLE `players` DROP INDEX `exp`");

或者我还能做些什么呢?因为添加和删除索引非常昂贵。但是我可能会每10分钟缓存一次。

4 个答案:

答案 0 :(得分:3)

绝对没有。

构建索引比扫描整个表需要更多时间,因此会严重降低性能。

只需构建一次索引然后离开。

答案 1 :(得分:1)

SELECT * FROM players ORDER BY `exp` DESC

这需要阅读整个表并对其进行排序。

mysql_query("ALTER TABLE `players` ADD INDEX ( `exp` )");
$query = mysql_query("SELECT * FROM players ORDER BY `exp` DESC");
mysql_query("ALTER TABLE `players` DROP INDEX `exp`");

这需要读取整个表,对其进行排序,将排序结果写入磁盘,从磁盘读取它们,然后将其删除:将表锁定的所有内容。

第一个选项更快,更好用于并发。

如果你创建一个永久索引,它会更快。

10k记录太少,无法担心DML表现。

答案 2 :(得分:0)

使用“一次性”索引

O(n*log(n)) + O(n) + [cost of index delete - don't know this]

生成索引

O(n) - 订购时,O(log(N))INSERT

UPDATE exp column个额外时间

O(n)O(n*log(n)) + O(n)快得多,然后您生成索引并离开,但如果exp上的多次更改比{{1}更改你需要考虑不要索引这个列,因为它总体上更长。或者使用其他解决方案,例如ORDER by exp缓存排序的SELECT

exp的缓存结果是解决此问题的最佳解决方案,但选择时不选择SELECTADDING,因为这没有感。

答案 3 :(得分:0)

Artefacto是对的,更糟糕​​的是,改变一个表是一个阻塞程序,这意味着你所有的选择和更新都会在这个过程中堆积起来。如果您的数据库有任何负载,这将破坏它。使用索引或不使用索引,但不要构建和销毁它。