Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php MySQL查询需要花费很多时间来加载?如何高效地优化数据库_Php_Mysql_Sql_Indexing_Query Optimization - Fatal编程技术网

Php MySQL查询需要花费很多时间来加载?如何高效地优化数据库

Php MySQL查询需要花费很多时间来加载?如何高效地优化数据库,php,mysql,sql,indexing,query-optimization,Php,Mysql,Sql,Indexing,Query Optimization,我有一个表,目前包含大约500万行。这是一个实时数据库,其中数据是由一个刮脚本填充的。该脚本不断地将数据插入表中, 例如: 业务列表站点在API调用时给我一个JSON响应,该响应被解析并插入到数据库中。其间还会进行重复检查。在稍后的阶段,我将获取获得的数据以获取报告 尝试根据存储的信息获取报告时,脚本执行时间过长。 刮取脚本是活动的,并且在将来继续使用记录更新表。 每个月它都有望获得0.7-1百万个新记录 以下是我的表格结构 CREATE TABLE IF NOT EXISTS `biz_lis

我有一个表,目前包含大约500万行。这是一个实时数据库,其中数据是由一个刮脚本填充的。该脚本不断地将数据插入表中, 例如:

业务列表站点在API调用时给我一个JSON响应,该响应被解析并插入到数据库中。其间还会进行重复检查。在稍后的阶段,我将获取获得的数据以获取报告

尝试根据存储的信息获取报告时,脚本执行时间过长。 刮取脚本是活动的,并且在将来继续使用记录更新表。 每个月它都有望获得0.7-1百万个新记录

以下是我的表格结构

CREATE TABLE IF NOT EXISTS `biz_listing` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `lid` smallint(11) NOT NULL,
  `name` varchar(300) NOT NULL,
  `type` enum('cat1','cat2') NOT NULL,
  `location` varchar(300) NOT NULL,
  `businessID` varchar(300) NOT NULL,
  `reviewcount` int(6) NOT NULL,
  `city` varchar(300) NOT NULL,
  `categories` varchar(300) NOT NULL,
  `result_month` varchar(10) NOT NULL,
  `updated_date` date NOT NULL,
  PRIMARY KEY (`id`),
  KEY `biz_date` (`businessID`,`updated_date`),
  KEY `type_date` (`type`,`updated_date`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
这些记录分为两类,“一类”和“二类”。 (我计划添加一个新类别,比如cat3)

我需要有一个相同的station aggregate report部分,它显示在所选月份范围内每个月的业务ID

此处选择2014年6月至7月

总人数报告#类别

SELECT COUNT(t.`businessID`) AS bizcount, SUM(t.reviewcount) AS reviewcount, t.`type` 
FROM `biz_listing` t 
INNER JOIN 
( SELECT `businessID`,count(*) c FROM `biz_listing` WHERE updated_date BETWEEN '2014/06/01' AND LAST_DAY('2014/07/01') GROUP 
BY `businessID`,`type` HAVING c = 2 ) t2 
ON t2.`businessID` = t.`businessID` 
WHERE updated_date BETWEEN '2014/07/01' AND LAST_DAY('2014/07/01') GROUP BY t.`type`
解释(在400万备份表上完成)

总人数报告#基于城市

SELECT COUNT(t.`businessID`) AS bizcount, SUM(t.reviewcount) AS reviewcount, t.`type`, t.`location` as city  
FROM `biz_listing` t 
INNER JOIN 
( SELECT `businessID`,count(*) c FROM `biz_listing` WHERE updated_date BETWEEN '2014/06/01' AND LAST_DAY('2014/07/01') GROUP 
BY `businessID`,`type` HAVING c = 2 ) t2 
ON t2.`businessID` = t.`businessID` 
WHERE updated_date BETWEEN '2014/07/01' AND LAST_DAY('2014/07/01') GROUP BY t.`location`, t.`result_month`
这里我们选择月份范围(6月至7月),因此它将列出这两个月范围内的所有
businessID
通用项

第一次查询将根据业务类型输出

第二次查询将根据位置输出

问题是执行查询需要相当长的时间(600秒或更长),而且有时查询在完成之前就结束了

如果您发现有,请向我建议查询的优化

我认为索引正在影响抓取脚本的插入性能。 考虑到插入和检索性能,如何修改当前脚本?

提前准备好

编辑

我尝试了建议的覆盖指数,它比平常花费了更多的时间:(

解释如下:


这是一个MyISAM表,与InnoDB相比,它在插入查询和报告查询之间提供的争用更少。因此,让我们首先关注报告查询。索引确实会减慢插入速度。但是查询会因为缺少或不正确的索引而减慢很多速度

为了解决这个性能问题,我认为,清晰地考虑不同的子查询是有帮助的。 让我们从其中一个开始

SELECT `businessID`,
       count(*) c 
 FROM `biz_listing`
 WHERE updated_date BETWEEN '2014/06/01' AND LAST_DAY('2014/07/01')
 GROUP BY `businessID`,`type` 
HAVING c = 2 
这个子查询很简单,基本上构造得很好。它能够使用一个索引跳转到满足更新日期范围标准的第一条记录,然后线性扫描该索引以查找最后一条记录。当它扫描索引时,如果它在其中找到
type
列,它可以收集它需要满足的记录计数在扫描索引时通过查询。这很快

但是,你没有那个索引!所以这个子查询正在做一个完整的表扫描。正如我们在新英格兰所说的,这太慢了

如果您将您的复合覆盖索引
(类型,更新日期)
索引并交换其中两列的顺序以给出
(更新日期,类型)
,它将用作此查询的高性能覆盖索引。复合索引中列的显示顺序不正确,因此索引对此查询有帮助

让我们从同样的角度来看第一个主查询(省略子查询)

(这里有点不清楚。您在这里说
COUNT(t.businessID)
,但您可能想要
COUNT(DISTINCT t.businesscount)
。您所拥有的将给出与
COUNT(*)相同的结果,因为
businessID
没有空值。如果您这样做,您可以将
放入SUM(DISTINCT businessID)>2
,并且不再需要子查询。)

此查询的工作方式与前一个查询类似。它扫描
更新日期范围内的索引,然后按
类型
,然后拾取
businessID
reviewcount
的值。因此,按此顺序的复合索引将允许通过快速的纯索引扫描来满足此查询

(updated_date, type, businessID,reviewcount)
请注意,可以从
(updated\u date,type)
索引中满足的任何查询也可以从这个索引中满足,因此您不需要同时满足这两个查询

阅读复合覆盖索引、窄范围扫描和宽范围扫描

同样的索引可能会大大改进您的其他查询。请尝试一下

您似乎有一个备份表。您可以在该表中尝试各种复合索引,直到获得良好的结果

我不愿意给出这样的建议:

TL;DR:将索引从这个更改为那个

因为那时你可能会带着下一个问题回到原来的状态,并被诱惑成为一个支持吸血鬼


你知道……教人钓鱼等等。

你听说过解释吗?@JohnRuddell Sry,我现在已经添加了。好的,你已经设置了索引吗?日期是以那种格式存储的吗?谢谢你的快速响应,然后在查询中更改日期的格式。。匹配格式。你也可以查看日期的间隔,即m在速度方面可能会有一些帮助。问题在于没有索引的
have
子句。你应该尝试在任何时候添加索引,进行多行比较,因此当你将一个表与另一个表连接时,你应该在两个表的PK和FK上有一个索引。这将提高速度。Ollie的回答有助于理解e索引也是如此……我建议研究一下,看看添加索引的最佳方法,以及在连接表(性能方面)以添加no时的关键瓶颈在哪里
(updated_date, type, businessID,reviewcount)