【发布时间】:2020-12-13 11:23:35
【问题描述】:
我有很好的书面功能;我想,但是当我在一个有很多事务的客户端上使用这个函数时,它需要大约 20 秒,每次我添加新事务时都会增加。此功能从一开始就开始重新计算所有客户债务。 我正在使用:
- WAMP 服务器 3.1.4
- PHP 7.2.10
- MYSQL 5.7.23
我已经尝试在 php.ini 中进行一些更改
php.ini
post_max_size = 256M
upload_max_filesize = 128M
memory_limit = 1G
max_input_vars = 10000
和
my.ini
key_buffer_size = 256M
max_allowed_packet = 128M
sort_buffer_size = 128M
net_buffer_length = 8K
read_buffer_size = 128M
read_rnd_buffer_size = 128M
myisam_sort_buffer_size = 512M
innodb_buffer_pool_size = 256M
innodb_log_file_size = 256M
innodb_log_buffer_size = 512M
[mysqldump]
quick
max_allowed_packet = 512M
[isamchk]
key_buffer_size = 512M
sort_buffer_size = 128M
read_buffer_size = 256M
write_buffer_size = 256M
[myisamchk]
key_buffer_size = 512M
sort_buffer_size_size = 512M
read_buffer_size = 256M
write_buffer_size = 256M
这是函数
function reCalculateAll($conn, $clid, $cltp){
$stmt = $conn->prepare("SELECT * FROM transactions WHERE client_id = ? AND client_type = ? ORDER BY STR_TO_DATE(transaction_date, '%d/%m/%Y %H:%i:%s') ASC");
$stmt->bind_param('is', $clid, $cltp);
$stmt->execute();
$results = $stmt->get_result();
$stmt->fetch();
$numberofrows = $stmt->num_rows;
while ($row = $results->fetch_assoc()) {
$r = getAllTransactionsClient($conn, $clid, $cltp);
$result = array();
foreach($r as $i => $p){
$result[$p['client_type'].$p['client_id']][] = $p;
foreach ($result as $rr){
foreach ($rr as $c => $k){
reset($rr);
$trid = $k['id'];
$trcn = $k['client_id'];
$trtp = $k['client_type'];
$trdt = $k['transaction_date'];
if($c === key($rr)){
// FIX TRANSACTION
$addm = 0;
$stmtf = $conn->prepare("UPDATE transactions SET client_oldfunds = ?, client_newfunds = ? + added_amount where id = ?");
$stmtf->bind_param('ssi', $addm, $addm, $trid);
$stmtf->execute();
$stmtf->close();
$addm = $k['client_newfunds'];
} else {
$stmtn = $conn->prepare("UPDATE transactions SET client_oldfunds = ?, client_newfunds = ? + added_amount where id = ?");
$stmtn->bind_param('ssi', $addm, $addm, $trid);
$stmtn->execute();
$stmtn->close();
$addm = $k['client_newfunds'];
}
$cnf = getLastDebtFromTransaction($conn, $trtp, $trcn);
setDebts($conn, $trtp, $cnf, $trcn);
}
}
}
}
$results->free();
$stmt->execute();
$stmt->store_result();
$numberofrows = $stmt->num_rows;
if($numberofrows == 0){
setDebts($conn, $cltp, '0', $clid);
}
$stmt->close();
}
getAllTransactionsClient 函数
function getAllTransactionsClient($conn, $clid, $cltp){
$stmt = $conn->prepare("SELECT * FROM transactions WHERE client_id = ? AND client_type = ? ORDER BY STR_TO_DATE(transaction_date, '%d/%m/%Y %H:%i:%s') ASC");
$stmt->bind_param('is', $clid, $cltp);
$stmt->execute();
$result = $stmt->get_result();
$products = array();
while ($row = $result->fetch_assoc()) {
$products[] = $row;
}
return $products;
$stmt->close();
}
【问题讨论】:
-
您介意告诉我们一些指标吗?我们在谈论多少交易?正在执行多少更新查询?
-
@MagnusEriksson 什么样的指标?你是说数据吗?
-
编辑问题以包含
SHOW CREATE transactions输出。桌子有多大。在循环中进行更新不是数据库友好的。 SQL 服务器可以很好地循环,因此您不需要这样做。 reCalculateAll 应该是一条 SQL 语句。语句准备应该在循环之外。欢迎来到 SO -
指标是指数字。如果您的选择查询返回 2 个要迭代的事务,那么 20 秒就很多了。如果您的选择查询返回 1.000.000 个事务,那么 20 秒是相当快的(因为您在循环中更新它们)。
-
@danblack 感谢您花时间阅读我的问题并回答它,我将尝试找到一种方法来替换这个多个循环,但我在压力下创建了这段代码,并且很快就修复了我的软件有问题,仍在寻找更好的想法