此行以下的所有内容都已过期。 Magento只是很慢,没有更多,仅此而已。
由于HostGator缺少root权限而陷入困境之后,我最终会自行分析Magento的调用。
以下是其中一项结果:
Blue: timing 1982878436 Mage_Sales_Model_Mysql4_Quote begin
< - 输入Mage_Sales_Model_Mysql4_Quote
的{{1}}方法时会记录此信息。
save
< - 并在退出时记录。
数字Blue: timing 1982878436 Mage_Sales_Model_Mysql4_Quote 46
是作为通话ID生成的随机数。数字1982878436
是以秒为单位的时间。
46
我们可以看到2012-09-26T06:36:16+00:00 DEBUG (7): Blue: timing 1982878436 Mage_Sales_Model_Mysql4_Quote begin
2012-09-26T06:36:18+00:00 DEBUG (7): Blue: timing 645597828 Mage_Log_Model_Mysql4_Visitor begin
2012-09-26T06:36:18+00:00 DEBUG (7): Blue: 645597828 Varien_Db_Adapter_Pdo_Mysql
2012-09-26T06:36:18+00:00 DEBUG (7): Blue: timing 645597828 Mage_Log_Model_Mysql4_Visitor 0
2012-09-26T06:36:18+00:00 DEBUG (7): Blue: timing 1712949075 Mage_Sales_Model_Mysql4_Quote begin
2012-09-26T06:36:24+00:00 DEBUG (7): Blue: timing 2103820838 Mage_Sales_Model_Mysql4_Quote begin
2012-09-26T06:36:56+00:00 DEBUG (7): Blue: timing 1999314779 Mage_Log_Model_Mysql4_Visitor begin
2012-09-26T06:36:56+00:00 DEBUG (7): Blue: 1999314779 Varien_Db_Adapter_Pdo_Mysql
2012-09-26T06:36:56+00:00 DEBUG (7): Blue: timing 1999314779 Mage_Log_Model_Mysql4_Visitor 0
2012-09-26T06:36:56+00:00 DEBUG (7): Blue: timing 504509596 Mage_Sales_Model_Mysql4_Quote begin
2012-09-26T06:36:56+00:00 DEBUG (7): Blue: timing 1887845167 Mage_Log_Model_Mysql4_Visitor begin
2012-09-26T06:36:56+00:00 DEBUG (7): Blue: timing 1887845167 Mage_Log_Model_Mysql4_Visitor 0
2012-09-26T06:37:02+00:00 DEBUG (7): Blue: timing 1887308594 Mage_GoogleOptimizer_Model_Mysql4_Code begin
2012-09-26T06:37:02+00:00 DEBUG (7): Blue: timing 1887308594 Mage_GoogleOptimizer_Model_Mysql4_Code 0
2012-09-26T06:37:02+00:00 DEBUG (7): Blue: 504509596 Varien_Db_Adapter_Pdo_Mysql
2012-09-26T06:37:02+00:00 DEBUG (7): Blue: timing 504509596 Mage_Sales_Model_Mysql4_Quote 6
2012-09-26T06:37:02+00:00 DEBUG (7): Blue: 1982878436 Varien_Db_Adapter_Pdo_Mysql
2012-09-26T06:37:02+00:00 DEBUG (7): Blue: timing 1982878436 Mage_Sales_Model_Mysql4_Quote 46
2012-09-26T06:37:02+00:00 DEBUG (7): Blue: 1712949075 Varien_Db_Adapter_Pdo_Mysql
2012-09-26T06:37:02+00:00 DEBUG (7): Blue: timing 1712949075 Mage_Sales_Model_Mysql4_Quote 44
2012-09-26T06:37:02+00:00 DEBUG (7): Blue: 2103820838 Varien_Db_Adapter_Pdo_Mysql
2012-09-26T06:37:02+00:00 DEBUG (7): Blue: timing 2103820838 Mage_Sales_Model_Mysql4_Quote 38
,1982878436
,1712949075
并行调用,每个都需要几十秒才能完成。我怀疑这三个电话中有一些锁定问题让他们互相等待。有时当我保存产品时,Magento甚至会报告因为死锁导致MySQL失败而导致操作失败。
有人对此有任何想法吗?
答案 0 :(得分:4)
当您在IN
内运行查询时,MySQL
始终会使最外层的桌子处于领先地位。
这意味着此查询:
UPDATE {$this->getTable('sales/quote')} SET trigger_recollect = 1
WHERE entity_id IN (
SELECT DISTINCT quote_id
FROM {$this->getTable('sales/quote_item')}
WHERE product_id IN (SELECT DISTINCT product_id FROM {$this->getTable('catalogrule/rule_product_price')})
必须扫描sales/quote
中的每条记录,并针对sales/quote_item
进行检查,而catalogrule/rule_product_price
则必须检查每条匹配的记录与sales/quote
。
如果UPDATE {$this->getTable('catalogrule/rule_product_price')} crpp
JOIN {$this->getTable('sales/quote_item')} sqi
ON sqi.product_id = crpp.product_id
JOIN {$this->getTable('sales/quote')} sq
ON sq.entity_id = sqi.quote_id
SET sq.trigger_recollect = 1
中的记录明显多于子查询返回的记录,则速度会很慢。
您可能希望将其重写为连接:
{{1}}
这样,优化器可以选择哪个表作为前导(当每个连接字段被索引时,它应该是最小的表)。
答案 1 :(得分:2)
最终只有其他查询阻止了这些查询。在这个问题上有两个主要的减速。
一个是在Mage / Sales / Model / Mysql4 / Quote.php中,有两个嵌套查询。我既不知道MySQL的缓存如何工作,也不知道如何在HostGator上配置MySQL,所以我最终自己缓存了查询结果:
public function markQuotesRecollectOnCatalogRules()
{
/*
$this->_getWriteAdapter()->query("
UPDATE {$this->getTable('sales/quote')} SET trigger_recollect = 1
WHERE entity_id IN (
SELECT DISTINCT quote_id
FROM {$this->getTable('sales/quote_item')}
WHERE product_id IN (SELECT DISTINCT product_id FROM {$this->getTable('catalogrule/rule_product_price')})
)"
);
*/
$products = $this->_getReadAdapter()->fetchCol("SELECT DISTINCT product_id FROM {$this->getTable('catalogrule/rule_product_price')}");
$ids = $this->_getReadAdapter()->fetchCol("
SELECT DISTINCT quote_id
FROM {$this->getTable('sales/quote_item')}
WHERE product_id IN (?)", implode(',', $products)
);
if (count($ids) > 0)
{
$this->_getWriteAdapter()->query("
UPDATE {$this->getTable('sales/quote')} SET trigger_recollect = 1
WHERE entity_id IN (?)", implode(',', $ids)
);
}
}
和
public function markQuotesRecollect($productIds)
{
/*
$this->_getWriteAdapter()->query("
UPDATE `{$this->getTable('sales/quote')}` SET `trigger_recollect` = 1
WHERE `entity_id` IN (
SELECT DISTINCT `quote_id`
FROM `{$this->getTable('sales/quote_item')}`
WHERE `product_id` IN (?)
)", $productIds
);
*/
$ids = $this->_getReadAdapter()->fetchCol("
SELECT DISTINCT quote_id
FROM {$this->getTable('sales/quote_item')}
WHERE product_id IN (?)", $productIds
);
if (count($ids) > 0)
{
$this->_getWriteAdapter()->query("
UPDATE {$this->getTable('sales/quote')} SET trigger_recollect = 1
WHERE entity_id IN (?)", implode(',', $ids)
);
}
return $this;
}
还有Mage / CatalogRule / Model / Rule.php。在内部,它似乎是一个众所周知的重新索引问题。
public function applyAllRulesToProduct($product)
{
$this->_getResource()->applyAllRulesForDateRange(NULL, NULL, $product);
$this->_invalidateCache();
/*
$indexProcess = Mage::getSingleton('index/indexer')->getProcessByCode('catalog_product_price');
if ($indexProcess) {
$indexProcess->reindexAll();
}
*/
if ($product instanceof Mage_Catalog_Model_Product)
{
$id = $product->getId();
}
else
{
$id = $product;
}
if ($id)
{
$indexer = Mage::getResourceSingleton('catalog/product_indexer_price');
if ($indexer)
{
$indexer->reindexProductIds(array($id));
}
}
}
我认为应对全球环境应该是更好的方式。但我没有时间,所以我复制了这个解决方案。