这个问题很难描述,因此很难找到答案。我希望有些专家能就此分享你的意见。
我有一张约有100万条记录的表格。表结构类似于以下内容:
items{
uid (primary key, bigint, 15)
updated (indexed, int, 11)
enabled (indexed, tinyint, 1)
}
场景是这样的。我必须每天选择所有记录并进行一些处理。处理每件物品大约需要3秒钟。
我编写了一个PHP脚本,每次使用以下内容获取200个项目。
select * from items where updated > unix_timestamp(now()) - 86400 and enabled = 1 limit 200;
然后,我将更新所选项目的“已更新”字段,以确保在一天内不会再次选择它。选定的查询就是这样的。
update items set updated = unix_timestamp(now()) where uid in (1,2,3,4,...);
然后,PHP将继续运行并处理不再需要任何MYSQL连接的数据。
由于我有数百万条记录,每条记录需要3秒才能处理,因此按顺序执行它绝对不可能。因此,我将每10秒执行一次PHP。
然而,随着时间的推移和表的增长,选择变得慢得多。有时,运行需要100多秒!
你们有什么建议我怎么解决这个问题?
答案 0 :(得分:3)
我认为有两点值得帮助:
一个。 unix_timestamp(now()) - 86400)
...这将为每一行评估now(),通过在每次运行之前将变量设置为该值使其成为常量。
湾索引可以帮助读取但可以减慢写入速度
在更新之前考虑删除索引(DISABLE KEYS) - 然后在读取之前重新添加它们(ENABLE KEYS)。
答案 1 :(得分:2)
我不认为enabled
上的索引对你有任何好处,基数太低了。删除它,你的UPDATE
应该更快。
当你说每个记录需要3秒钟时,我不确定你是什么意思,你是在200个批次处理它们。你如何确定这个以及涉及哪些其他处理?
答案 2 :(得分:2)
你可以这样做:
dispatcher.php
:管理整个过程。
worker.php
(我知道worker.php
不需要超过UID来完成其工作)worker.php
个程序员。当一个启动时,计数器递增直到某个限制,当一个工人返回时,计数器递减。请参阅"Asynchronous PHP calls?“。LIMIT
计数器,但不能使用updated
。worker.php
:做实际的工作
dispatcher.php
:做家务。
您将拥有这种多线程处理链,甚至可以将整个事物分布在多台计算机上。
答案 3 :(得分:1)
您可以在更新前尝试运行此功能:
ALTER TABLE items DISABLE KEYS;
然后当你完成更新时,
ALTER TABLE items ENABLE KEYS;
这应该比一次更新每条记录更快地重建索引。
答案 4 :(得分:0)
对于记录少于几十亿的表,主键应该是unsigned int而不是bigint。
答案 5 :(得分:0)