优化高索引表上的INSERT/UPDATE查询


Optimize INSERT / UPDATE query on highly indexed tables

我正在使用一个基于OpenCart 1.5.6.4的网站,该网站对原始网站进行了高度修改(添加了索引,修改了查询,你能想到的,只是为了性能(。

服务器是一个VPS,具有2 x 2GHz处理器50GB SSD4GB RAM。目前有CentOS6Apache 2.2.15MySQL 5.1.73。该网站是一个在线商店,拥有大约50000种产品以及9家供应商。

整个系统的初始逻辑是:

  • 在不同的"缓冲"表中从供应商处进口所有产品

  • 在不同的"缓冲"表中导入供应商的所有产品类别(用于映射目的(

  • 更新网站中的产品。。。禁用不再可用的产品,或根据以下规则更新现有产品的价格和库存:"如果供应商之间有通用产品,则在库存为0的情况下采用最低价格!否则采用最低价格"。

我在更新过程中遇到了一些麻烦。我尝试了一些不同的脚本(选择多个表上的EACH 2个表之间通用的所有值(,但只运行一个查询大约需要3秒。

我没有太多OOP经验,所以我使用数组:我将所有产品数据加载到一个数组中,将排除列表加载到另一个数组,检查第一个数组中的产品是否未设置在第二个数组中。对规则进行数学运算,并使用批量INSERT [...] ON DUPLICATE KEY UPDATE [...]写入数据。

整个更新需要很长时间,大约需要20秒并"吃掉">65%的CPU(基于phpmyadmin中的读数(。我需要一个解决方案:运行速度非常快(我不介意CPU(,或者需要更长的时间,但对CPU的影响较小。。。基本上,服务器上有大约8个连接,大约有50%的CPU使用率,这意味着原始的update.php崩溃了。

我尝试添加了LOCK TABLES product WRITE、query、UNLOCK TABLES,但性能提高了0.x秒。UPDATE过程在一个查询中有大约40000个产品。。。它花费的时间太长,占用的CPU太多,而且锁表的时间很长。

我该怎么办?

LE:代码在这里http://inpromo.ro/update.txt

基本上有9个分销商,有网站类别和分销商类别(必须映射…未映射的类别不会在网站中添加其产品(,也有制造商必须映射(同一制造商可以显示为:华硕或华硕组件(,诸如此类的事情。。。

LE2:一个查询看起来像:

更新产品集合stock_status_id=5,数量=0,状态=0,其中状态=1或数量=0或stock_status_id=5

它需要2-3秒才能完成(根据PHP的microtime((函数(,这太多了!

谁在触发此更新?

1( 一个正常的在线用户

2( 一个cron作业

3( 你在行政部门吗?

也许您还可以发布代码行或您正在使用的查询。

附言:你没有使用OOP并不是坏事,但你在不了解OOP的情况下在opencart这样的OOP平台上工作是坏事。。。。

阅读此

由于整个脚本在代码块上运行,我注意到对于所有现有产品,我都在索引表上使用了"INSERT[…]on DUPLICATE KEY UPDATE[…]",如:productdescription,product_category,product_to_store(这些表不包含股票、价格等关键数据(,整个过程额外占用了90MB内存和大量处理时间(约12秒(。

现在的逻辑是:

  • 在复制密钥更新[…]上插入product[…](批量插入/更新所有产品(
  • "SELECT p.product_id,p.sku FROM product p LEFT JOIN product_to_store ps ON p.product_id=ps.product_id WHERE ps.production_id为NULL AND p.status=1"…只是为了加载新项目
  • 插入到productdescription、product_category、product_to_store。。。新产品的详细信息

很抱歉问了一些看似平庸的问题,你试过这些东西吗:

  • mysql和php配置的调整
  • 使用EXPLAIN语句并尝试更改索引
  • 将"联接"查询拆分为小型"非联接"查询,然后查看"长查询日志"以查看瓶颈所在
  • 在更新/插入之前,是否在表上使用了"锁"?(这可能是一个愚蠢的问题,因为opencart可以有自己的mysql类来做这件事,但我真的不知道(
  • 尝试处理一个单独的表(使用非"on duplicate key update"(,然后更新"live"表(使用简单的"INSERT INTO table_live SELECT*FROM table_2 GROUP BY someting and bla bla you know better"(

希望我有一些想法。