当在查询中包含子查询时,MySQL将CPU提高到100%

当在查询中包含子查询时,MySQL将CPU提高到100%,mysql,Mysql,提前感谢你的帮助 我的服务器突然达到100%的CPU使用率。在关闭所有脚本并逐渐恢复它们之后,我将问题追溯到一种在两个地方使用的特定类型的查询。查询如下: select * from zzproductdata where amazonproductid <> '' and amazoncategory1 ='' and disabled = 0 and productid in (select productid from zzdropshipstock where quantit

提前感谢你的帮助

我的服务器突然达到100%的CPU使用率。在关闭所有脚本并逐渐恢复它们之后,我将问题追溯到一种在两个地方使用的特定类型的查询。查询如下:

select * from zzproductdata
where amazonproductid <> '' and amazoncategory1 ='' and disabled = 0
and productid in (select productid from zzdropshipstock where quantity >= 10)
在第一个查询中使用EXPLAIN-我得到以下结果:

这是我在终端中看到的:

我试过添加DISTINCT,但没有效果。它降低了CPU使用率的升级速度,因此需要将近200秒才能达到100%的CPU使用率,但它没有运行查询


查询的第一部分在0.23秒内返回1300000条记录。子查询在2.3秒内返回118000条记录。这是当您分别运行这两个部分时。将这两个查询组合到一个查询中,当前应该返回大约15000条记录。

我不完全确定MySQL如何处理vs EXISTS中的数据,但大体上说,您应该首选EXISTS而不是IN,因为EXISTS子句在第一次匹配时返回true,然而,在确定是否存在匹配之前,可能必须创建完整的集合-这可能会导致高内存使用率。但我不确定MySQL的情况。我知道这个问题存在于MSSQL 2005和2008中,如果同样的问题存在于MySQL的现代版本中,我也不会感到惊讶,因为它没有一些企业级RDMS那么完美

请仔细阅读,试试下面的代码,看看它是否能改善情况:

select *
from zzproductdata as pd
where amazonproductid <> ''
and amazoncategory1 =''
and disabled = 0
and exists (
    select *
    from zzdropshipstock as dss
    where quantity >= 10
    and pd.productid = dss.productid
)

对于start,您可以尝试添加以下索引:

更改表zzdropshipstock添加索引IXZZDropShipStock_键数量、productid

更改表zzproductdata添加索引IXZZProductData_productid productid


然后执行分析表zzdropshipstock,分析表zzproductdata并显示新的解释计划。

在zzproductdata和zzdropshipstock表上有索引吗?如果您提供SHOW CREATE TABLE zzproductdata,那就太好了;输出以及这些查询的解释信息。您是否尝试将DISTINCT添加到子查询中?您还可以在添加DISTINCT之后,将子查询移动到FROM中,并将其内部联接到其中。与许多其他条件相比,MySQL不能很好地处理或处理条件,IN基本上是一个OR,尽管我知道在最新版本中对IN进行了优化。我不认为这有什么帮助。对于第一个查询,我认为问题在于“发送数据”的结果太多。我认为amazonproductid和amazoncategory1=和disabled=0在其中适用于大多数记录1.5M,子查询中可能有相当多的产品。这就是我要求解释的原因。针对150万行的相关子查询可能会让事情变得更糟。虽然IN必须创建一个完整的集合,但它只创建一次;EXISTS必须对每个相关的外部行执行,并且成本越高,找到现有记录的可能性越小,删除的成本就越高。感谢您的建议。这并没有改善情况。它只是让CPU在12秒内达到100%,而不是90秒。我不知道达到最大CPU的速度的提高是否有助于确定问题。@uuerExists必须执行它吗?SQL并不意味着,适当的查询优化程序会将其转换为内部连接。问题不在于是否存在,而在于其中查询的相关性质。我同意相关子查询的性质更难实现。这就是为什么优化器经常将其转换为子查询中的连接。不幸的是,在不了解sql版本、现有数据和服务器可用统计信息的情况下,这只是猜测。每个表中的productid之间没有索引,因为这会导致其他地方的查询速度大幅降低。即使没有两个productid字段之间的索引,它也可以在5.6秒内正常运行,然后在下一次运行时停止工作。我相信您是正确的,添加这些索引将解决此查询的特定问题,我可能必须这样做,然后更改其他脚本与这些表相关的工作方式。但非常奇怪的是,它将在5.6秒内正常运行,然后停止运行并最大限度地利用CPU。索引不应使其他查询慢得多,插入/更新可能会慢得多。目前,SQL server必须在每个表中处理150万行。太多了。内存不足,交换开始。如果没有索引,则无法修复此问题。以前,表中的数据较少时,它可以存储在内存中,因此速度相当快。是的,不幸的是,这两个表每小时都有1000次插入,每小时也有10000次编辑。通过添加这些索引,可以显著降低插入速度。如果我理解正确,我的选择是要么增加服务器上的内存,要么添加索引/接受插入所需的额外时间。然后你必须找到另一种方法。您不能期望SQL server将“连接”两个1.5M的表,而这些表中没有索引
合理的时间。您可以添加更多RAM,但在另外两周内您将面临相同的问题。我不相信每小时1000次插入和10000次更新会受到建议索引的严重影响。只需尝试添加至少第二个建议索引。您也可以尝试优化插入:谢谢,我会尝试一下。谢谢你的帮助,伙计。
CREATE TABLE `zzproductdata` (
 `zzproductdataid` int(11) NOT NULL AUTO_INCREMENT,
 `zzproductdataname` text NOT NULL,
 `disabled` int(11) NOT NULL,
 `datecreated` date NOT NULL,
 `masteronly` int(11) NOT NULL,
 `productid` int(11) NOT NULL,
 `isbn` text NOT NULL,
 `ean` text NOT NULL,
 `publishername` text NOT NULL,
 `imagethumbnail` text NOT NULL,
 `imagefull` text NOT NULL,
 `amazonproductid` text NOT NULL,
 `productdatasource` text NOT NULL,
 `datelastupdatedamazon` date NOT NULL,
 `datelastupdatedgoogle` date NOT NULL,
 `googleproductid` text NOT NULL,
 `publicationdate` date NOT NULL,
 `binding` text NOT NULL,
 `imagescollecteddate` date NOT NULL,
 `amazoncategory1` text NOT NULL,
 `amazoncategory2` text NOT NULL,
 `amazoncategory3` text NOT NULL,
 `datelastcheckedamazoncategory` date NOT NULL,
 `datelastupdatedopenlibrary` date NOT NULL,
 PRIMARY KEY (`zzproductdataid`)
)
ENGINE=InnoDB
AUTO_INCREMENT=1674296
DEFAULT CHARSET=utf

CREATE TABLE `zzdropshipstock` (
 `zzdropshipstockid` int(11) NOT NULL AUTO_INCREMENT,
 `zzdropshipstockname` text NOT NULL,
 `disabled` int(11) NOT NULL,
 `datecreated` date NOT NULL,
 `masteronly` int(11) NOT NULL,
 `zzdropshipsupplierid` int(11) NOT NULL,
 `isbn` varchar(13) NOT NULL,
 `quantity` double NOT NULL,
 `suppliercode` text NOT NULL,
 `supplierprice` double NOT NULL,
 `standardshipcost` double NOT NULL,
 `weightgram` double NOT NULL,
 `rrp` double NOT NULL,
 `productid` int(11) NOT NULL,
 `initialimportdate` date NOT NULL,
 `lastupdateddate` date NOT NULL,
 `changed` int(11) NOT NULL,
 `lastcheckedproductiddate` date NOT NULL,
 `lastcheckedproductinamazondate` date NOT NULL,
 `lastcheckedrawstockdata` date NOT NULL,
 `lastcheckedproductstockitemlive` date NOT NULL,
 `changedquantity` int(11) NOT NULL,
 PRIMARY KEY (`zzdropshipstockid`),
 KEY `isbn` (`isbn`)
)
ENGINE=InnoDB
AUTO_INCREMENT=7037817
DEFAULT CHARSET=latin1
select *
from zzproductdata as pd
where amazonproductid <> ''
and amazoncategory1 =''
and disabled = 0
and exists (
    select *
    from zzdropshipstock as dss
    where quantity >= 10
    and pd.productid = dss.productid
)