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

时间:2014-12-26 10:59:01

标签: php mysql

我正在使用基于 OpenCart 1.5.6.4 的网站,该网站已经过原始版本的高度修改(添加的索引,已修改的查询,您只需为了性能而命名)。

服务器是具有 2 x 2GHz处理器 50GB SSD 4GB RAM 的VPS。目前它有 CentOS 6 Apache 2.2.15 MySQL 5.1.73 。该网站是一个在线商店,约有 50,000个产品和9个供应商。

整个系统的初始逻辑是:

  • 从不同的"缓冲区"中导入供应商的所有产品。表

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

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

我在使用更新程序时遇到了一些麻烦。我尝试了一些不同的脚本(Select all values that are common between EACH 2 tables on several tables),但只运行1次查询大约需要3秒钟。

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

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

我已尝试添加LOCK TABLES product WRITE,查询UNLOCK TABLES,但性能提升了0.x秒。 UPDATE过程在一个查询中有大约40,000个产品...它需要太长时间,它使用太多CPU并长时间锁定表。

我该怎么办?

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

基本上有9个分销商,有网站类别和分销商类别(必须映射...未映射的类别不要在网站上添加他们的产品),还有制造商也必须映射(同一制造商可以显示为:华硕或华硕组件),像这样......

LE2:一个查询如下:

更新产品SET stock_status_id = 5,数量= 0,状态= 0 WHERE状态= 1或数量!= 0或stock_status_id!= 5

完成需要2-3秒(根据PHP的microtime()函数)并且这很多!

3 个答案:

答案 0 :(得分:0)

谁在触发此次更新?

1)普通在线用户

2)cron工作

3)你在管理中?

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

PS:你没有使用OOP也不错,但是你在不知道OOP的情况下使用opencart这样的OOP平台是不好的。

read this

答案 1 :(得分:0)

由于整个脚本在代码块上运行,我注意到对于所有现有产品,我在索引表上使用了“INSERT [...] ON DUPLICATE KEY UPDATE [...]”,如: product_description,product_category,product_to_store(这些表不包含库存,价格等关键数据),整个过程需要额外的90MB内存和一大堆处理时间(~12秒)。

现在的逻辑是:

  • INSERT INTO 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.product_id IS NULL AND p.status = 1”...只是为了加载新项< / LI>
  • 插入product_description,product_category,product_to_store ...新产品的详细信息。

答案 2 :(得分:0)

对于提出明显平庸的问题感到抱歉,你试过这些事吗:

  • 调整mysql和php配置
  • 使用EXPLAIN语句并尝试更改索引
  • 分裂&#39;加入&#39;小额加入&#39;非查询查询,然后看看和长查询日志&#39;看看瓶颈在哪里
  • 你在使用&#39;锁定&#39;在更新/插入之前在桌子上? (这可能是一个愚蠢的问题,因为opencart可能有自己的mysql类,但我不知道)
  • 尝试在单独的表格上工作(非重复密钥更新&#39;)然后更新&#39; live&#39; table(简单&#39; INSERT INTO table_live SELECT * FROM Table_2 GROUP BY someting and bla bla bla你知道更好&#39;)

希望我能提出一些想法。