Mysql SQL查询运行非常慢

Mysql SQL查询运行非常慢,mysql,Mysql,我有一个sql查询,用于收集库存中所有产品的年初至今总计。这个查询运行得很快,在一秒钟多一点的时间内返回大约5000个结果 使用的查询是 SELECT `ITINCODE` as Code, `IT_product_id` as ID, SUM(IF(YEAR(`ITDATE`) = YEAR(CURDATE() ), IF(ITTYPE = "O",`ITVAL`, -`ITVAL` ), 0) ) as 'YTD_VAL' FROM `FITEMS` WHERE (ITTYPE = 'O'

我有一个sql查询,用于收集库存中所有产品的年初至今总计。这个查询运行得很快,在一秒钟多一点的时间内返回大约5000个结果

使用的查询是

SELECT `ITINCODE` as Code, `IT_product_id` as ID,
SUM(IF(YEAR(`ITDATE`) = YEAR(CURDATE() ), IF(ITTYPE = "O",`ITVAL`, -`ITVAL` ), 0) ) as 'YTD_VAL'
FROM `FITEMS`
WHERE (ITTYPE = 'O' OR `ITTYPE` = 'R') AND ITBACKORDER = 'N' AND ITAMNT > 0 AND YEAR(`ITDATE`) >= YEAR(CURDATE() ) -1
GROUP BY `ITINCODE`
ORDER BY YTD_VAL DESC
我想获取YTD_VAL中的值,并将其存储在实际产品表中,以便在其他查询中用作ORDER BY。我在products表中添加了一个名为ytd_val的新字段,然后运行

UPDATE products p SET p.ytd_val = 
(SELECT SUM(IF(YEAR(`ITDATE`) = YEAR(CURDATE() ), IF(ITTYPE = 'O',`ITVAL`, -`ITVAL` ), 0) ) as 'YTD_VAL'
FROM `FITEMS`
WHERE ITINCODE  = p.products_model AND (ITTYPE = 'O' OR `ITTYPE` = 'R') AND ITBACKORDER = 'N' AND ITAMNT > 0 AND YEAR(`ITDATE`) >= YEAR(CURDATE() ) -1
GROUP BY `ITINCODE`
ORDER BY YTD_VAL DESC)
我们的想法是每晚运行cron作业,以便更新值以反映前几天的销售额

然而,运行这个查询已经花费了10多分钟,而且还没有完成

FITEMS表中的ITINCODE与products表中的products\U型号相同。 FITEMS表中的IT_product_id与products表中的products_id相同

如何加快查询速度?我认为,由于原始结果查询返回的速度足够快,只需更新另一个表上的值就需要几秒钟的时间

表结构如下:

show create table fitems\G;

Create Table: CREATE TABLE `fitems` (
  `ITUNIQUEREF` int(11) unsigned NOT NULL,
  `ITAMNT` int(11) NOT NULL,
  `ITREF` int(11) unsigned NOT NULL,
  `ITTYPE` char(1) NOT NULL,
  `ITVAL` decimal(10,4) NOT NULL,
  `ITVAT` decimal(10,4) NOT NULL,
  `ITPRICE` decimal(10,4) NOT NULL,
  `ITDATE` date NOT NULL,
  `ITBACKORDER` char(1) NOT NULL,
  `ITDISC` decimal(10,2) NOT NULL,
  `ITORDERREF` int(11) NOT NULL,
  `ITTREF` int(11) unsigned NOT NULL,
  `ITDATEDLY` date NOT NULL,
  `ITINCODE` char(20) NOT NULL,
  `IT_product_id` int(11) unsigned NOT NULL,
  `ITBUILT` int(11) NOT NULL,
  PRIMARY KEY (`ITUNIQUEREF`),
  KEY `ITREF` (`ITREF`,`ITTYPE`,`ITDATE`,`ITBACKORDER`,`ITORDERREF`,`ITDATEDLY`,`ITINCODE`,`IT_product_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;


如果您对第一个查询的性能感到满意

您可以将第二个查询转换为使用内部联接,如:

更新,顺便说一句,你不需要YTD_VAL DESC的订单,我想在这种特殊情况下没有意义

更新2


如果您对第一个查询的性能感到满意

您可以将第二个查询转换为使用内部联接,如:

更新,顺便说一句,你不需要YTD_VAL DESC的订单,我想在这种特殊情况下没有意义

更新2

选择总是比更新快得多

要加快更新速度,请执行以下操作:

查看您正在更新的表上的索引:它们都是必需的吗?如果没有,删除不需要的,我至少会删除idx_产品_状态_zen,因为这也包含在产品_状态_产品_价格中

看看数据模型:您能对正在更新的表进行分区吗?如果是这样,那将加快更新速度,因为您正在更新的索引将更小,因此更新速度更快

使用InnoDB。它更快

您需要符合ACID要求吗?如果没有,则更改InnoDB的设置以加速系统

如果你真的在使用MySQL:切换到MariaDB:大约快8%

安装监控以查看瓶颈在哪里:IO或CPU:如果是读取时的IO,请尝试压缩

选择总是比更新快得多

要加快更新速度,请执行以下操作:

查看您正在更新的表上的索引:它们都是必需的吗?如果没有,删除不需要的,我至少会删除idx_产品_状态_zen,因为这也包含在产品_状态_产品_价格中

看看数据模型:您能对正在更新的表进行分区吗?如果是这样,那将加快更新速度,因为您正在更新的索引将更小,因此更新速度更快

使用InnoDB。它更快

您需要符合ACID要求吗?如果没有,则更改InnoDB的设置以加速系统

如果你真的在使用MySQL:切换到MariaDB:大约快8%

安装监控以查看瓶颈在哪里:IO或CPU:如果是读取时的IO,请尝试压缩


我不是说要做这件事,而是考虑覆盖指数的情况。特别是在餐桌上。对于该查询,这些列相对较小。我会找一个来试一试特定的栏目。我们已经看到过这样的情况:非常长的查询可以在短时间内完成。但没有承诺。啊,我看你有一些。正在查看第一次编辑,下面是alter表格。我会继续找的

覆盖指数 覆盖索引是一种可以通过索引b树快速遍历来解析查询的索引,而不需要查找实际的表数据页。这是速度的终极涅盘。关于它的快速文章

解释 然后运行查询,并逐个更新并检查输出。另见文章


注意,有些评论是针对下面的,不一定是OP。他似乎把他的房子安排得很好。

< P>我不是说要做它,而是考虑覆盖索引的情况。特别是在餐桌上。对于该查询,这些列相对较小。我会找一个来试一试特定的栏目。我们已经看到过这样的情况:非常长的查询可以在短时间内完成。但没有承诺。啊,我看你有一些。正在查看第一次编辑,下面是alter表格。我会继续找的

覆盖指数 覆盖索引是一种可以通过索引b树快速遍历来解析查询的索引,而不需要查找实际的表数据页。这是速度的终极涅盘。关于它的快速文章

解释 然后运行查询,并逐个更新并检查输出。另见文章

注意,其中一些评论是针对以下内容,而不是ne
当然是这个op。他似乎把他的房子整理得很好。

在子查询中,order by和group by都不是必需的,因此更新可以写成:

UPDATE products p
    SET p.ytd_val = (SELECT SUM(IF(YEAR(`ITDATE`) = YEAR(CURDATE() ), IF(ITTYPE = 'O',`ITVAL`, -`ITVAL` ), 0) )
                     FROM `FITEMS`
                     WHERE FITEMS.ITINCODE = p.products_model AND
                           ITTYPE IN ('O', 'R') AND
                           ITBACKORDER = 'N' AND
                           ITAMNT > 0 AND
                           YEAR(`ITDATE`) >= YEAR(CURDATE() ) - 1
                    );

为此,您需要FITEMSITINCODE、ITBACKORDER、ITTYPE、itmnt、ITVAL上的索引。这可能会大大加快查询速度。

在子查询中,不需要order by或group by,因此更新可以写成:

UPDATE products p
    SET p.ytd_val = (SELECT SUM(IF(YEAR(`ITDATE`) = YEAR(CURDATE() ), IF(ITTYPE = 'O',`ITVAL`, -`ITVAL` ), 0) )
                     FROM `FITEMS`
                     WHERE FITEMS.ITINCODE = p.products_model AND
                           ITTYPE IN ('O', 'R') AND
                           ITBACKORDER = 'N' AND
                           ITAMNT > 0 AND
                           YEAR(`ITDATE`) >= YEAR(CURDATE() ) - 1
                    );


为此,您需要FITEMSITINCODE、ITBACKORDER、ITTYPE、itmnt、ITVAL上的索引。这可能会大大加快查询速度。

显示each@Drew我已经添加了CREATETABLE语句,以及两个表的主键信息。这个表太复杂了,需要处理多个表。例如,列products\u group\u a\u price到products\u group\u g\u price尖叫,如果您需要H怎么办?您还使用了太多的索引,这将减慢更改表的操作。请看,这些索引是由zen cart的作者设置的,可能还有一些是由以前的开发人员添加的。如果我向您展示一个普通安装上的索引数量,您会感到震惊。该products表中的所有第9栏字段都是zen cart中的原始字段。要开始拆分表,可能需要跨数百个文件进行大量工作。我同意,该结构还有很多需要改进的地方,但是每次更新核心时,在该级别进行更改将导致巨大的复杂性each@Drew我添加了CREATETABLE语句,以及两个表的主键信息。该表过于复杂,并且试图完成多个表的工作。例如,列products\u group\u a\u price到products\u group\u g\u price尖叫,如果您需要H怎么办?您还使用了太多的索引,这将减慢更改表的操作。请看,这些索引是由zen cart的作者设置的,可能还有一些是由以前的开发人员添加的。如果我向您展示一个普通安装上的索引数量,您会感到震惊。该products表中的所有第9栏字段都是zen cart中的原始字段。要开始拆分表,可能需要跨数百个文件进行大量工作。我同意,这个结构还有很多需要改进的地方,但是每次核心更新时,在这个级别上进行更改将导致巨大的复杂性。他在MyISAM上。他的全文搜索索引可能会根据版本要求使用MyISAM。感谢@Drew:Do拆分你的表,这样全文索引就可以单独管理了。Norbert干得不错。好久没见了:@Drew:是的,重复的评论是:请看我写的,答案是他在MyISAM上。他的全文搜索索引可能会根据版本要求使用MyISAM。感谢@Drew:Do拆分你的表,这样全文索引就可以单独管理了。Norbert干得不错。好久没见你了:@Drew:是的,重复的评论是:请看我写的,答案是肯定的,原始查询返回4150行,但更新查询只报告2803行受影响的行。我在这里暗中摸索,但可能不是所有原始ITINCODE行都有匹配的products\u模型。我将尝试使用IT\u products\u id和products\u idinstead@StevePrice . . . 原始代码将不匹配的产品和模型值设置为NULL。这个版本没有改变它们,我的意思是,只收集数据的原始查询,不更新另一个表,返回4150个结果。我们假设如果有4150个结果可用,那么应该更新结果的数量。请显示SELECT COUNTDISTINCT products_model FROM products的结果?顺便问一下,您的查询速度加快了吗?Stangely,原始查询返回4150行,但更新查询只报告2803个受影响的行。我在这里暗中摸索,但可能不是所有原始ITINCODE行都有匹配的products\u模型。我将尝试使用IT\u products\u id和products\u idinstead@StevePrice . . . 原始代码将不匹配的产品和模型值设置为NULL。这个版本没有改变它们,我的意思是,只收集数据的原始查询,不更新另一个表,返回4150个结果。我们假设如果有4150个结果可用,那么应该更新结果的数量。请显示SELECT COUNTDISTINCT products_model FROM products的结果?顺便问一下,您的查询速度加快了吗?
UPDATE products p 
    INNER JOIN (
      SELECT SUM(IF(YEAR(`ITDATE`) = YEAR(CURDATE() ), IF(ITTYPE = 'O',`ITVAL`, -`ITVAL` ), 0) ) as 'YTD_VAL',
      IT_product_id 
    FROM `FITEMS`
    WHERE (ITTYPE = 'O' OR `ITTYPE` = 'R') 
      AND ITBACKORDER = 'N' AND ITAMNT > 0 AND YEAR(`ITDATE`) >= YEAR(CURDATE() ) -1
    GROUP BY `IT_product_id`
      ) t
    ON t.IT_product_id = p.products_id 
    SET p.ytd_val = t.YTD_VAL
UPDATE products p
    SET p.ytd_val = (SELECT SUM(IF(YEAR(`ITDATE`) = YEAR(CURDATE() ), IF(ITTYPE = 'O',`ITVAL`, -`ITVAL` ), 0) )
                     FROM `FITEMS`
                     WHERE FITEMS.ITINCODE = p.products_model AND
                           ITTYPE IN ('O', 'R') AND
                           ITBACKORDER = 'N' AND
                           ITAMNT > 0 AND
                           YEAR(`ITDATE`) >= YEAR(CURDATE() ) - 1
                    );