- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我是 stackoverflow 的新手,对于这么长的问题,请接受我的歉意。我有一个零售店的大型数据库。我们想准备一份报告来获取产品的期初和期末余额,产品有批号,每个批处理都有分配给多个位置的唯一序列号。挑战在于获取每个仓库位置的每批选定产品的期初余额。如果报告过滤器中未指定位置,则报告应给出每个位置的选定产品及其所有批处理的结果。
我使用 PHP/PDO 获取所有位置并循环遍历它,在第一个循环中,我获取针对所选产品的所有批处理,在批处理循环中,我首先获取期初余额(计算方式如下:开始日期过滤器之前的数量),然后我计算该产品批处理在该位置的接收数量(开始日期和截止日期过滤器中接收的数量总和),然后销售数量或移动到其他仓库的数量(移动数量总和)到所选起始日期和截止日期过滤器内的其他仓库)。
我现在可以计算期末余额,因为我拥有所有值。这运行良好,但是当查询运行 20 个仓库并且单个产品有近 20 多个批处理时,报告需要很长时间才能处理,并且 MySQL CPU 使用率高达 200%。
我尝试优化查询,我的表已正确编入索引。表有很多数据。数百万条记录。我需要有关如何改进我的代码或方法、我做错了什么以及如何更快地生成报告的建议。
我正在为我的应用程序使用 code igniter,下面是代码。
foreach($locations as $loc){
//if batch is selected put it in array
if($query_array['batch_no'] != ''){
$batches[] = $query_array['batch_no'];
}else{
// or get all batches from the inventory table for the location
$this->db->select('distinct(batch_no)');
$this->db->from('product_details');
$this->db->where('product_id',$query_array ['product']);
$this->db->where('warehouse_id',$loc);
$query = $this->db->get();
foreach($query->result() as $row){
$batches[] = $row->batch_no;
}
$query->free_result();
}
foreach($batches as $batch){
//GIN IN Opening Balance
$this->db->select('IFNULL(SUM(gi.qty),0) as gin_in',FALSE);
$this->db->from('gin as g');
$this->db->join('gin_items as gi','gi.gin_id=g.id');
$this->db->where('gi.product_id',$query_array ['product']);
$this->db->where('DATE(g.creation_date) < ',$query_array ['date_from']);
$this->db->where('g.to_location_id', $loc);
$this->db->where_in('gi.batch_no',$batch);
$this->db->where_in('gi.status',2);
$this->db->where('g.status',3);
$query = $this->db->get();
if($query->num_rows()==1)
{
$var1=$query->row()->gin_in;
$query->free_result();
}
// SUM (Return Invoices for a specific product, for this particular store,
// before this date range) -> $var2
$this->db->select('IFNULL(SUM(ii.qty),0) as sale_return_in',FALSE);
$this->db->from('return_sales_invoice rs');
$this->db->join('return_invoice_items as ii','ii.invoice_id=rs.id');
$this->db->where('ii.medicine_id',$query_array ['product']);
$this->db->where_in('ii.batch_no',$batch);
$this->db->where_in('rs.location_id',$loc);
$this->db->where('rs.dated < ',$query_array ['date_from']);
$query = $this->db->get();
if($query->num_rows()==1){
$var2=$query->row()->sale_return_in;
$query->free_result();
}
//SUM (Sales Invoices of a specific product, from this particular store,
// before this date range) -> $var3
$this->db->select('IFNULL(SUM(ii.qty),0) as sale_out',FALSE);
$this->db->from('sales_invoice si');
$this->db->join('invoice_items as ii','ii.invoice_id=si.id');
$this->db->where('ii.medicine_id',$query_array ['product']);
$this->db->where_in('ii.batch_no',$batch);
$this->db->where_in('si.location_id',$loc);
$this->db->where('si.dated < ',$query_array ['date_from']);
$query = $this->db->get();
if($query->num_rows()==1){
$var3=$query->row()->sale_out;
$query->free_result();
}
// SUM (GIN of a specific product, from this particular store,
// before this date range) -> $var4
// if from location then minis stock
$this->db->select('IFNULL(SUM(gi.qty),0) as gin_out',FALSE);
$this->db->from('gin as g');
$this->db->join('gin_items as gi','gi.gin_id=g.id');
$this->db->where('DATE(g.creation_date) < ',$query_array ['date_from']);
$this->db->where('gi.product_id',$query_array ['product']);
$this->db->where_in('gi.batch_no',$batch);
$this->db->where_in('g.from_location_id',$loc);
$this->db->where('gi.status',2);
$this->db->where('g.status',3);
$query = $this->db->get();
if($query->num_rows()==1){
$var4=$query->row()->gin_out;
$query->free_result();
}
$op_bal = ($var1 + $var2) - ($var3 + $var4);
//---------------------------------------------------------------------------------
$where_from = "DATE(g.creation_date) >='" . $query_array ['date_from'] . "'";
$where_to = "DATE(g.creation_date) <='" . $query_array ['date_to'] . "'";
$rs_where_from = "DATE(rs.creation_date) >='" . $query_array ['date_from'] . "'";
$rs_where_to = "DATE(rs.creation_date) <='" . $query_array ['date_to'] . "'";
$si_where_from = "DATE(si.creation_date) >='" . $query_array ['date_from'] . "'";
$si_where_to = "DATE(si.creation_date) <='" . $query_array ['date_to'] . "'";
//GIN IN Opening Balance
$this->db->select('IFNULL(SUM(gi.qty),0) as gin_in',FALSE);
$this->db->from('gin as g');
$this->db->join('gin_items as gi','gi.gin_id=g.id');
$this->db->where($where_from);
$this->db->where($where_to);
$this->db->where('gi.product_id',$query_array ['product']);
$this->db->where_in('gi.batch_no',$batch);
$this->db->where_in('g.to_location_id', $loc);
$this->db->where('g.status',3);
$this->db->where('gi.status',2);
$query = $this->db->get();
if($query->num_rows()==1){
$g_stock_in=$query->row()->gin_in;
$query->free_result();
}
// SUM (Return Invoices for a specific product, for this particular store,
// before this date range) -> $var2
$this->db->select('IFNULL(SUM(ii.qty),0) as sale_return_in',FALSE);
$this->db->from('return_sales_invoice rs');
$this->db->join('return_invoice_items as ii','ii.invoice_id=rs.id');
$this->db->where('ii.medicine_id',$query_array ['product']);
$this->db->where($rs_where_from);
$this->db->where($rs_where_to);
$this->db->where_in('ii.batch_no',$batch);
$this->db->where_in('rs.location_id',$loc);
$query = $this->db->get();
if($query->num_rows()==1){
$s_stock_in=$query->row()->sale_return_in;
$query->free_result();
}
//SUM (Sales Invoices of a specific product, from this particular store,
// before this date range) -> $var3
$this->db->select('IFNULL(SUM(ii.qty),0) as sale_out',FALSE);
$this->db->from('sales_invoice si');
$this->db->join('invoice_items as ii','ii.invoice_id=si.id');
$this->db->where('ii.medicine_id',$query_array ['product']);
$this->db->where_in('ii.batch_no',$batch);
$this->db->where_in('si.location_id',$loc);
$this->db->where($si_where_from);
$this->db->where($si_where_to);
$query = $this->db->get();
if($query->num_rows()==1){
$s_stock_out=$query->row()->sale_out;
$query->free_result();
}
// SUM (GIN of a specific product, from this particular store,
// before this date range) -> $var4
// if from location then minis stock
$this->db->select('IFNULL(SUM(gi.qty),0) as gin_out',FALSE);
$this->db->from('gin as g');
$this->db->join('gin_items as gi','gi.gin_id=g.id');
$this->db->where($where_from);
$this->db->where($where_to);
$this->db->where('gi.product_id',$query_array ['product']);
$this->db->where_in('gi.batch_no',$batch);
$this->db->where_in('g.from_location_id',$loc);
$this->db->where('g.status',3);
$this->db->where('gi.status',2);
$query = $this->db->get();
if($query->num_rows()==1){
$g_stock_out=$query->row()->gin_out;
$query->free_result();
}
$qty_in=$g_stock_in+$s_stock_in;
$qty_out=$g_stock_out+$s_stock_out;
$productName=$this->getProductName($query_array ['product']);
$locationName=$this->getLocationName($loc);
$data [] = array (
'location' => $locationName,
'product' => $productName,
'batchno' => $batch ,
'op_bal' => $res['op_bal'] ,
'qty_in' => $qty_in,
'qty_out' => $qty_out,
'cl_bal' => ($res['op_bal'] + $qty_in ) - $qty_out
);
}
}
return $data;
最佳答案
您认识到您在这个报告程序中做了很多事情。特别是您正在进行大量单结果行查询。与编写较少的为每个项目返回一行的查询相比,这通常被认为对性能有害。
您的问题的一个可能解决方案是:在晚上运行报告程序,不要为糟糕的性能而烦恼。你会完成工作的。这种通宵批处理在现实世界中相当普遍。
另一种解决方案:将数据库视为返回表的机器,而不仅仅是值。重构您的查询以返回多个结果。您最终会得到少得多的查询,并且您将能够利用 DBMS 的查询规划器一次提取大量信息。例如,不是在 php 中循环定位,而是让 MySQL 这样做。
这将为您提供批处理、仓库和产品的列表,每行一行。
SELECT DISTINCT batch_no, warehouse_id, product
FROM product_details
ORDER BY batch_no, warehouse_id, product
接下来,我想这个查询会为您提供所需的结果之一,但针对所有批处理、仓库和产品。 “我猜”是因为您没有透露您的架构或业务规则。此查询来自组合程序中的前两个查询。
SELECT SUM(gi.qty) gin_in, p.batch_no, p.warehouse_id, p.product
FROM product_details p
JOIN gin g ON g.to_location_id = p.warehouse_id
JOIN gin_items gi ON gi.gin_id = g.id AND gi.product_id = p.product
WHERE DATE(g.creation_date) < $date_from
AND g.status = 3
GROUP BY p.batch_no, p.warehouse_id, p.product
您明白了:让您的查询返回很多行,而不是运行无数次查询,每次只返回一行。
关于php - MySQL/PHP,ForEach 循环缓慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38033845/
我最近从 Indigo“升级”到了 Luna(Oracle OEPE 安装)。请注意围绕“升级”一词的引用。 不幸的是,事情很慢。 我使用的项目是一个 Maven 多模块项目。构建工作区操作大约需要
如果我的 JavaScript 事件似乎都不是网页性能问题的原因,我该如何诊断网页性能问题? 我有一个使用jqGrid的网络应用程序。单击网格会导致 2-3 秒的卡住,然后发生任何事情(包括点击任何单
从 appengine 访问我的应用程序时,我经常收到以下错误。有人可以知道这是什么原因吗? 原因:com.google.apphosting.api.DeadlineExceededExceptio
出于某种原因,我的 curl 调用非常慢。这是我使用的代码。 $postData = "test" $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $
Stackdriver 测试我的网站启动速度慢 我们使用 cloudflare 作为我们的站点 CDN 提供商。我们使用 stackdriver 从外部测试站点可用性,我们将时间检查间隔设置为 1 分
在插入/更新许多行时,我知道SQLite的“问题”,但事实并非如此。 我正在更新包含约250条记录的表中的ONE一行(由PK索引)中的ONE字段。查询通常需要200毫秒左右的时间。听起来很少,但很大。
我们的 Mongo 数据库会定期(有时每天一次)变慢约 30-40 分钟。在此缓慢时期,访问数据库的 API 会遇到每 5-10 分钟就会出现一次的高延迟峰值。 查看 mongod 日志文件,这两
这个问题已经在这里有了答案: 已关闭8年。 Possible Duplicate: C# WinForm Application - UI Hangs during Long-Running Oper
我最近将我的 Java Liquibase 版本从 3.5.3 升级到 3.6.3 我有一个非常繁重的环境,其中有很多数据库和表(我使用的是 Oracle)。 在这种环境下,我试图执行一个巨大的变更日
在我的项目中,为了整洁起见,模块被组织在子目录中。 我的项目目录层次结构: $ ls -R .: configure.in Makefile.am Makefile.cvs src
我正在 Debian 上使用存储库中的软件包运行 Gitlab。大多数时候Gitlab运行速度非常快,但是在较长的空闲时间后Gitlab非常慢甚至超时(错误502)。有一次我在远程 git 访问上也遇
这可能是菜鸟的错误,所以请原谅我。我在高处和低处寻找解决方案,但没有结果-因此,我想在此添加第一篇文章:-) 我有两个域类,一个称为Domain,一个称为Page。如下代码所示,域中有许多页面。 cl
我是 React 的新手,在使用 onChange 时遇到了问题在大数据列表中生成的输入字段上的方法。 如 parentcomponent是数据的拥有者,我提供了handleUpdate()子组件 (
我们使用 Webpack DefinePlugin 为不同的渲染模式生成输出包。因此,例如,我们的 webpack 配置将返回 [{ entry: { mode1: "./in
我在页面顶部有一个带有菜单的标题元素。当我向下滚动时,标题会动画到较低的高度。当我向上滚动并到达顶部时,标题会以动画方式显示为原始大小。 但它的工作并不完美。有时,事情发生之前需要两秒钟。特别是当我向
我今天在我的文本编辑器(Sublime)中写了一些正则表达式,试图快速找到特定的源代码段,这需要有点创意,因为有时函数调用可能包含更多函数调用。例如,我正在寻找 jQuery 选择器: $("div[
ParentSadly 我没有通过搜索“laggy/slow mouse wheel-scrolling in Rich Edit control”和类似的句子找到答案。 我创建了一个丰富的编辑控件
我遇到了“OR”运算符在 mysql 中未使用任何索引的典型性能问题: SELECT sms.smsID, sms.phonenumber, sms.text, date, mbr.name, mbr
我最近一直在玩 asyncio 模块。下面是我想出的用于发送一些并行请求的代码,这些请求在我的笔记本电脑 (Mac OS) 上似乎运行良好,但在另一台机器 (Ubuntu 18.04) 上似乎运行缓慢
我目前正在开发一个并行应用程序(C#、WinForms),它通过 COM 将消息注入(inject)应用程序。 此应用程序使用多个 foreach 语句,从接受 COM 的应用程序中轮询实体指标。 L
我是一名优秀的程序员,十分优秀!