[英]How to use SQL in the most efficient way with very big tables
I have a table purchase
something like ( id
, buyer_id
, seller_id
, amount
) with 20-30 millions of records Also i have a table with the same structure purchase_archive
and table users_balance
( id
, user_id
, balance
) 我有一个表, purchase
类似的信息( id
, buyer_id
, seller_id
, amount
)20-30百万的记录此外,我有相同结构的表purchase_archive
和表users_balance
( id
, user_id
, balance
)
I should write a script that: 我应该写一个脚本:
purchase
to purchase_archive
table 将记录从purchase
移动到purchase_archive
表 users_balance
should be updated (user balance should be decreased for amount
if he is a buyer, and increased for the same amount if he is a seller) 对于每个移动的行,应该更新users_balance
(如果他是买方,则应减少用户余额的amount
如果他是卖方,则应增加相同金额的用户的余额) What is the best way to solve this task? 解决此任务的最佳方法是什么? (PHP + Mysql PDO) (PHP + Mysql PDO)
My assumption is: 我的假设是:
For each row 每行
4.1 Store id in array ($temp) 4.1在数组中存储ID($ temp)
4.2 Update balance with query like 4.2用查询更新余额
SELECT `amount` FROM `purchase` WHERE `id` = :tid LIMIT 1 INTO @amount; UPDATE `users_balance` SET `balance` = CASE WHEN `user_id` = :seller_id THEN `balance` + @amount WHEN `user_id` = :buyer_id THEN `balance` - @amount END WHERE `user_id` IN (:buyer_id, :seller_id);
Move rows into archive with the query like that: 使用以下查询将行移动到存档中:
INSERT INTO `purchase_archive` SELECT * FROM `purchase` WHERE `id` IN (".$temp."); DELETE QUICK FROM `transactions` WHERE `id` IN (".$temp.");
End transaction 结束交易
And repeat 2-6 in cycle. 并重复2-6个循环。
The longest operation is point 4.2, and i dont know how to perform it faster without variables 最长的操作是4.2点,我不知道如何在没有变量的情况下更快地执行操作
Is there any faster approaches? 有没有更快的方法?
PS Sorry for my terrible english. PS对不起,我的英语不好。
You can try something like this: 您可以尝试如下操作:
update user_balance b
inner join (
select b.user_id,
sum(case when p.buyer_id = b.user_id then p.amount else 0 end) bought,
sum(case when p.seller_id = b.user_id then p.amount else 0 end) sold
from purchase p
inner join user_balance b
on p.buyer_id = b.user_id
or p.seller_id = b.user_id
group by b.user_id) q
on b.user_id = q.user_id
set b.amount = b.amount + q.sold - q.bought;
And it should do everything in a single query. 并且它应该在单个查询中完成所有操作。 You can limit the range further in the inner query if you wish. 如果需要,可以在内部查询中进一步限制范围。 SQL Fiddle seems to be down so I can't provide a live demo, but there is this: SQL Fiddle似乎已无法正常运行,因此我无法提供实时演示,但实际上是这样的:
mysql> select * from user_balance;
+---------+--------+
| user_id | amount |
+---------+--------+
| 1 | 50 |
| 2 | 50 |
| 3 | 50 |
| 4 | 50 |
+---------+--------+
4 rows in set (0.00 sec)
mysql> select * from purchase;
+-------------+-----------+----------+--------+
| purchase_id | seller_id | buyer_id | amount |
+-------------+-----------+----------+--------+
| 1 | 1 | 2 | 10 |
| 2 | 3 | 4 | 20 |
| 3 | 4 | 2 | 5 |
| 4 | 1 | 4 | 7 |
| 5 | 3 | 1 | 9 |
+-------------+-----------+----------+--------+
5 rows in set (0.00 sec)
and after the query.... 然后查询...。
mysql> update user_balance b inner join (select b.user_id, sum(case when p.buyer_id = b.user_id then p.amount else 0 end) bought, sum(case when p.seller_id = b.user_id then p.amount else 0 end) sold from purchase p inner join user_balance b on p.buyer_id = b.user_id or p.seller_id = b.user_id group by b.user_id) q on b.user_id = q.user_id set b.amount = b.amount + q.sold - q.bought;
Query OK, 4 rows affected (0.07 sec)
Rows matched: 4 Changed: 4 Warnings: 0
mysql> select * from user_balance;
+---------+--------+
| user_id | amount |
+---------+--------+
| 1 | 58 |
| 2 | 35 |
| 3 | 79 |
| 4 | 28 |
+---------+--------+
4 rows in set (0.00 sec)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.