我觉得我会因为问这个问题而被屠杀,但事情就是这样......
我的每日订阅量为 500 万,预计/希望在 12 个月内达到 5000 万。我需要非常非常快地续订/开具账单。我已经尝试了我能想到的索引和循环的所有排列,但它的 SELECT 查询仍然太慢。也许我的错误是 MySQL 设计,也许是我使用 MySQL 的守护进程,也许只是因为我正在使用 MySQL - 请让我知道您的想法和/或建议。谢谢!
** 订阅表看起来像这样 **
- subscription_id (PK)
- subscriber_id
- 服务编号
- 添加日期
- 当前开始日期
- 当前结束日期
- bill_date(用于确保两个线程不会同时抢帐)
- last_successful_bill_date
- 有_outstanding_balance
** Money-people-owe-me 表看起来像这样*
- 编号
- subscription_id(英国)
- 未结余额
- 下一个账单日期
- number_bill_attempts
- (相当多的人并不总是付费,我在继续尝试计费的同时给他们提供了一段时间的无偿访问权限,但最终我还是切断了他们的服务)
** Billing Daemon 看起来像这样 **
- 在多台机器上运行多线程:
- 对于每项服务
- stuffToBill[] = SELECT stuff ORDER BY next_bill_date FOR UPDATE LIMIT XXX;
- UPDATE stuff SET next_bill_date = later WHERE id IN (stuffToBill[ids])
- 提交
- 将他们放入计费人员的队列中
运行 EXPLAIN 显示我正在使用合适的索引,但是 SQL 的细节加上我在多个服务器上运行相同的守护程序的事实使得它锁定/通常使我的 DBM 上的 I/O 队列过载。 DBM 是优质硬件。
再次感谢您的建议!
最佳答案
您似乎正在使用选择/更新/提交机制来确定要向哪些帐户收费,如下所示:
SELECT stuff
ORDER BY next_bill_date
FOR UPDATE
LIMIT XXX;
UPDATE stuff
SET next_bill_date = later
WHERE id IN (stuffToBill[ids]);
COMMIT;
您的 SELECT 语句可以通过添加一个可行的 WHERE
子句来改进,该子句只选择即将到期的账单,或者通过一些其他标准。查看所有账单只是为了找到最旧的账单是没有意义的。有点像
WHERE next_bill_date <= TODAY() + INTERVAL 30 DAYS
可能会成功。如果您做对了,SELECT 查询的复杂性将会降低。如果您正确地为 next_bill_date 建立索引,您将可以使用索引。
您也可以尝试调整 LIMIT BY xxxx
值的大小。您可能在此处使用了太大的值,并且您的更新速度慢得令人不快。
最后,您将需要考虑进行一些严肃的 MySQL 和 InnoDB 调优。控制 RAM 使用等事项的预设参数通常不适合像您这样的生产系统。
关于高频计费系统的MySQL设计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19126895/