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

Php 我应该在一个页面中添加和删除索引吗?,php,mysql,optimization,Php,Mysql,Optimization,假设我有玩家表。它由3行组成(有更多行,但假设只有3行)成员id、姓名、经验。我在每页中使用member\u id行,所以我只在member\u id中添加索引。但是我想在一个页面中列出一个最高exp的顶级玩家名单。所以我就这样做: $query = mysql_query("SELECT * FROM players ORDER BY `exp` DESC"); 如果我有10k名玩家,如果不向exp添加索引,我就不能像这样运行查询。所以我的问题是,我应该这样做: mysql_query("A

假设我有
玩家
表。它由3行组成(有更多行,但假设只有3行)<代码>成员id、姓名、经验。我在每页中使用
member\u id
行,所以我只在
member\u 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分钟缓存一次,例如。

绝对不行

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

只需构建一次索引,然后将其保留。

使用“一次性”索引 已生成索引
O(n)
-在排序中,但是您在插入
更新exp列时有
O(log(n))
额外的时间


O(n)
O(n*log(n))+O(n)
快得多,然后生成索引并保留此项,但如果
exp
的更改比
ORDER by exp
多得多,则需要考虑不要为该列编制索引,因为它的总长度更长。或者使用其他解决方案,如
SELECT
exp
缓存排序


可能
SELECT
的缓存结果是该问题的最佳解决方案,但在不添加
删除索引的情况下执行此选择,因为这没有任何意义。

artifact是正确的,更糟糕的是,更改表是一个阻塞过程,这意味着所有的选择和更新都会在这期间堆积起来。如果您的数据库上有任何类型的负载,这将破坏它。要么使用索引,要么不使用,但不要构建和销毁索引

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的性能。

但是如果我缓存它并每10分钟运行一次这个查询?会这么糟糕吗?因为添加大量索引会使我的
更新
查询变慢,我想。@hey:你是不是每秒要向
players
表写入数百次?不要让对更新性能的毫无根据的担忧驱使您扭曲整个应用程序。好的。您不想在
exp
上建立永久索引的原因是什么?(顺便说一句,如果我的网站使用db凭据,允许它修改模式,这会让我感到紧张。)
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`");