我有一个比较网站,每天晚上我都会在上面更新商店的订阅源。这些通常不是最大的feed(即最大15000行),但是即使只有1000行的csv feed也可能需要很长时间,因为我必须执行(很多?)sql查询。这是我的程序:
每个csv feed都来自不同的分支网络,因此,有不同的索引和结构。这就是为什么我编写了一个页面,首先将每个提要标准化为正确的结构(即一个提要中的$row['name']=$col[1],而另一个提要中的$col[2])。这些“正确”数据将由另一个函数checkproduct()处理;。
在checkproduct()中,我首先检查产品是否已经存在。如果是,则更新标准信息:当前价格、库存、url等。如果不是,则将产品插入数据库。
但最后一点需要很长时间,甚至一个额外的查询也可能需要几分钟。我不认为这需要花费太长时间,但是我一直在寻找这段代码并寻找sql查询优化,但是我似乎不知道如何在批量或组合csv行时保持这个过程。我已经尝试过优化查询(使用count()而不是num_rows,只选择需要的列,等等)。
我不是编程Maven,但我知道一定有不同的选择。我知道可以将内容存储在一个数组中,然后循环该数组,或者使用load data infle,但我不知道在这种情况下如何编程(仍然对每一行进行相同的严格检查)。换言之:如何优化此代码?
这是函数checkproduct()
function CheckProduct($SiteID, $StoreID, $FeedID, $Name, $URL, $Description, $EANSKU, $Image, $Brand, $Color, $Price, $CategoryPath, $Stock, $Deliverycosts, $Deliverytime, $Length, $Width, $Depth, $Height, $Material)
{
global $db;
if ( !filter_var($URL, FILTER_VALIDATE_URL) === false && !filter_var($Image, FILTER_VALIDATE_URL) === false && !empty($Name) && !empty($URL) && !empty($Price) && !empty($Image) ) {
$sCountProduct = $db->query("SELECT COUNT(*) as total FROM furniture WHERE name_slug='".CreateSlug(trim($db->real_escape_string($Naam)))."' AND feed_id='".$FeedID."' LIMIT 1");
$fCountProduct = $sCountProduct->fetch_assoc();
if($fCountProduct['total'] == '0') {
$iProduct = $db->query("INSERT INTO furniture (site_id,feed_id,store_id,name,name_slug,affiliate_url,description,ean_sku,image_big,brand,brand_slug,color,color_slug,price,category_path,in_stock,visible,shipping_costs,check_today,last_update,deliverytime,length,width,depth,height,material,material_slug,added) VALUES ('1','".$FeedID."','".$StoreID."','".trim($db->real_escape_string($Name))."','".CreateSlug(trim($db->real_escape_string($Name)))."','".trim($AffiliateURL)."','".$db->real_escape_string(trim($Description))."', '".$db->real_escape_string(trim($EANSKU))."','".trim($Afbeelding)."','".$db->real_escape_string(trim($Brand))."','".CreateSlug($db->real_escape_string(trim($Brand)))."','".$db->real_escape_string(trim($Color))."','".CreateSlug($db->real_escape_string(trim($Color)))."','".$db->real_escape_string(trim($Price))."','".$db->real_escape_string(trim(strtolower($CategoryPath)))."','".$Stock."', '3','".$db->real_escape_string(trim($Deliverycosts))."','1','".time()."','".$db->real_escape_string(trim($Deliverytime))."','".$db->real_escape_string(trim($Length))."','".$db->real_escape_string(trim($Width))."','".$db->real_escape_string(trim($Depth))."','".$db->real_escape_string(trim($Height))."','".$db->real_escape_string(trim($Material))."','".CreateSlug($db->real_escape_string(trim($Material)))."','".date('d-m-Y')."')");
$IDProduct = $db->insert_id;
if($iProduct) {
$dOthers = $vm->query("DELETE FROM furniture WHERE name_slug='".CreateSlug(trim($db->real_escape_string($Name)))."' AND id != '".$IDProduct."' AND feed_id='".$FeedID."' AND visible != '1'");
}
}
else {
$sExistProduct = $db->query("SELECT id,site_id,name_slug,feed_id,price_old,visible,price FROM furniture WHERE site_id='1' AND name_slug='".CreateSlug(trim($db->real_escape_string($Name)))."' AND feed_id='".$FeedID."' LIMIT 1");
if(!$sExistProduct) { }
else {
// Check if it is a salesproduct
$fExistProduct = $sExistProduct->fetch_assoc();
$OudePrijs = $fExistProduct['price_old'];
$Zichtbaar = $fExistProduct['visible'];
if($fExistProduct['visible'] == '2'){ $Visible = '1'; }
if($Price < $fExistProduct['price']){ $OldPrice = $fExistProduct['price']; }
$uProduct = $db->query("UPDATE furniture SET affiliate_url='".trim($URL)."', description='".$db->real_escape_string(trim($Description))."', price='".$db->real_escape_string(trim($Price))."', price_old='".$db->real_escape_string(trim($OldPrice))."', in_stock='".$Stock."', shipping_costs='".$db->real_escape_string(trim($Deliverycosts))."', check_today='1', last_update='".time()."', deliverytime='".$Deliverytime."', visible='".$Visible."' WHERE id='".$fExistProduct['id']."' LIMIT 1");
if($uProduct) {
// Updated
}
}
}
}
else
{
// Error in image (not every image send by the feed is a good one)
}
}
以下是我处理某个提要以匹配正确列的方式:
$SiteID = '1';
$FeedID = '1';
$StoreID = '1';
$Link = 'URL';
if (($handle = fopen($Link, "r")) !== FALSE) {
fgetcsv($handle);
$i = 0;
while (($data = fgetcsv($handle, 6000, ";")) !== FALSE) {
$num = count($data);
for ($c=0; $c < $num; $c++){ $col[$c] = $data[$c]; }
### VARIABLES FROM FEED ###
$Name = $col[1];
$URL = $col[5];
$Description = strip_tags($col[4]);
$EANSKU = $col[0];
$Image = $col[6];
$Brand = $col[8];
$Color = '';
$Price = $col[3];
$CategoryPath = $col[9];
$Stock = $col[10];
$Deliverycosts = $col[14];
$Deliverytime = '';
$Length = '';
$Width = '';
$Height = '';
$Depth = '';
$Material = '';
### STOCK ###
if($Stock > 0) {
$Stock = '1';
}
else {
$Stock = '0';
}
### SEND PRODUCT ###
CheckProduct($SiteID, $StoreID, $FeedID, $Name, $URL, $Description, $EANSKU, $Image, $Brand, $Color, $Price, $CategoryPath, $Stock, $Deliverycosts, $Deliverytime, $Length, $Width, $Depth, $Height, $Material);
$i++;
}
fclose($handle);
}
我使用的是PHP5.6.32和MySQL5.0.11。
1条答案
按热度按时间carvr3hs1#
选择计数()不需要限制。。。
只需预先选择数据:选择name_slug,feed_id,count()as cnt as total from furniture group by name_slug,feed_id“);
选择name\u slug,feed\u id,id,site\u id,name\u slug,feed\u id,price\u old,visible,price from furniture where site\u id='1'
并将它们用作查找表。
然后对插入/删除/更新进行批处理,整个脚本所用的时间应该不到几秒钟。
或者在mysql中完成这一切。。。