假设我有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分钟缓存一次。
答案 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
的缓存结果是解决此问题的最佳解决方案,但选择时不选择SELECT
和ADDING
,因为这没有感。
答案 3 :(得分:0)
Artefacto是对的,更糟糕的是,改变一个表是一个阻塞程序,这意味着你所有的选择和更新都会在这个过程中堆积起来。如果您的数据库有任何负载,这将破坏它。使用索引或不使用索引,但不要构建和销毁它。