我有以下三个与Amazon API交互的功能。当我使用parse_orders_result函数时,似乎需要大约30秒才能完成。我通过运行此get_orders函数并注释掉parse_orders_result来发现这一点,并在3秒内完成do while循环的每次迭代。但是,当我运行解析的东西时,我需要在下面提到的30秒。如何改善此操作的性能?
GET_ORDERS函数:
public function get_orders($date)
{
$this->throttle = amazon_throttle::list_orders_throttle();
$this->endpoint = "mws.amazonservices.com";
$this->url = "https://mws.amazonservices.com/Orders/$date";
$this->action = "ListOrders";
$this->version = '2011-01-01';
$this->api = "/Orders/$date\n";
$this->options = array(
'Action' => 'ListOrders',
'OrderStatus.Status.1'=>'Unshipped',
'OrderStatus.Status.2'=>'PartiallyShipped',
'OrderStatus.Status.3'=>'Shipped',
'OrderStatus.Status.4'=>'Canceled',//Get all unshipped, partially shipped, shipped, and canceled orders. This will update these types of orders if their status changes on Amazon
'LastUpdatedAfter'=> date("c", strtotime('-1 Month')) //FIXME update this to reflect our download interval later
);
$this->create_signature();
try
{
$results = $this->send_request(); //commented out for testing
}
catch (Exception $e)
{
echo $e->getMessage();
return false;
}
//$results = sql::value("SELECT api_response from dhs.dbo.api_response where id = 444");
$xml = new SimpleXMLIterator($results); //make the iterator here so we can check for a nexttoken
$orders = $this->parse_orders_result($xml->ListOrdersResult->Orders);
if ($xml->ListOrdersResult->NextToken)
{
$next_token = (string)$xml->ListOrdersResult->NextToken;
do
{
$results = $this->get_orders_next_token($next_token);
$xml = new SimpleXMLIterator($results);
$returned = $this->parse_orders_result($xml->ListOrdersByNextTokenResult->Orders);
$orders = array_merge($orders, $returned);
if ($xml->ListOrdersByNextTokenResult->NextToken)
$next_token = (string) $xml->ListOrdersByNextTokenResult->NextToken;
else
$next_token = null;
}
while($next_token);
}
//this stored procedure creates patient_ids for each order (if the patient doesn't already exist) and updates the orders table with with their patient_id
sql::query('EXEC dhs.dbo.sp_create_patients');
return $orders;
}
PARSE_ORDERS_RESULT函数:
$xml->registerXPathNamespace('amz', 'https://mws.amazonservices.com/Orders/2011-01-01');
$orders = array();
foreach ($xml->Order as $order)
{
$last = null;
$name = explode(' ', preg_replace('/[^A-z ]/', '', (string) $order->BuyerName)); //remove all special characters
if (!isset($name[1]) || !$name[1])
{
$attn_last = explode(' ', preg_replace('/[^A-z ]/', '',$order->ShippingAddress->Name)); //remove all special characters
$pos = count($attn_last) - 1;
$last = $attn_last[$pos];
}
$phone = preg_replace('/[^0-9]/', '', (string) $order->ShippingAddress->Phone); //remove everything that is not an int
$phone = "(" . substr($phone, 0,3) . ")" . substr($phone,3, 3) . "-" . substr($phone, 6); //format phone number
//order and ship status are both int values tied to information in the db
$ship_method = array_search(strtoupper((string) $order->ShipmentServiceLevelCategory),
sql::two_column_array("SELECT id, description FROM dhs.dbo.shipping_method WHERE site IS NULL or site = 'AMAZON' "));
$order_status = array_search(strtoupper((string) $order->OrderStatus),
sql::two_column_array("SELECT id, description FROM dhs.dbo.order_status WHERE site IS NULL or site = 'AMAZON' "));
//you have to cast found elements as string or they are returned as SimpleXMLIterator objects and you can't get the value
$arr = array(
'order_code'=> (string) $order->AmazonOrderId,
'shipping_method'=>$ship_method,
'amount'=> (string) $order->OrderTotal->Amount,
'purchased_on' => date('Y-m-d H:i:s', strtotime($order->PurchaseDate)),
'market_id' => (string) $order->MarketplaceId[0],
'status'=> $order_status,
'site'=> 'AMAZON',
'last_update' => date('Y-m-d H:i:s'),
'employee_id'=>login::$id,
'addr1'=> (string) $order->ShippingAddress->AddressLine1,
'addr2'=>(string) $order->ShippingAddress->AddressLine2,
'city'=>(string) $order->ShippingAddress->City,
'state'=>(string) $order->ShippingAddress->StateOrRegion,
'zip'=>(string) $order->ShippingAddress->PostalCode,
'attention'=>(string) $order->ShippingAddress->Name,
'email'=>(string) $order->BuyerEmail,
'phone'=>$phone,
'first'=>array_shift($name), //remove the 0 element, use array shift so we can glue the rest of the array together for last name
'last'=>(implode(' ', $name)) ? implode(' ', $name): $last,
'fullname'=>(string) $order->BuyerName,
'unshipped_items'=> (string) $order->NumberOfItemsUnshipped
);
foreach ($arr as $k => $v)
$arr[$k] = strtoupper($v);
$id = sql::merge('dhs', 'dbo', 'orders', array('order_code', 'site'), $arr, 'id');
$arr['order_id'] = $id;
sql::merge('dhs', 'dbo', 'order_shipping', array('order_id'), $arr);
$orders[] = $arr;
}
return $orders;
}
不幸的是,我无法安装XDebugger(它是公司服务器而我没有获得许可)。但是,我可以提供更多的见解:
答案 0 :(得分:0)
问题肯定与我们对数据库运行的查询数量有关。我创建了一个新的merge语句,它接受一个多维数组,并从foreach循环中删除了不必要的查询,并将执行时间减少到24秒(通过do-while循环进行5次迭代)。以下是修订后的解析订单功能:
private function parse_orders_result(SimpleXMLIterator $xml)
{
$shipping_methods = sql::two_column_array("SELECT id, description FROM dhs.dbo.shipping_method WHERE site IS NULL or site = 'AMAZON' ");
$order_statuses = sql::two_column_array("SELECT id, description FROM dhs.dbo.order_status WHERE site IS NULL or site = 'AMAZON' ");
$xml->registerXPathNamespace('amz', 'https://mws.amazonservices.com/Orders/2011-01-01');
$orders = array();
foreach ($xml->Order as $order)
{
$last = null;
$name = explode(' ', preg_replace('/[^A-z ]/', '', (string) $order->BuyerName)); //remove all special characters
if (!isset($name[1]) || !$name[1])
{
$attn_last = explode(' ', preg_replace('/[^A-z ]/', '',$order->ShippingAddress->Name)); //remove all special characters
$pos = count($attn_last) - 1;
$last = $attn_last[$pos];
}
$phone = preg_replace('/[^0-9]/', '', (string) $order->ShippingAddress->Phone); //remove everything that is not an int
$phone = "(" . substr($phone, 0,3) . ")" . substr($phone,3, 3) . "-" . substr($phone, 6); //format phone number
//order and ship status are both int values tied to information in the db
$ship_method = array_search(strtoupper((string) $order->ShipmentServiceLevelCategory), $shipping_methods);
$order_status = array_search(strtoupper((string) $order->OrderStatus), $order_statuses);
//you have to cast found elements as string or they are returned as SimpleXMLIterator objects and you can't get the value
$arr = array(
'order_code'=> (string) $order->AmazonOrderId,
'shipping_method'=>$ship_method,
'amount'=> (string) $order->OrderTotal->Amount,
'purchased_on' => date('Y-m-d H:i:s', strtotime($order->PurchaseDate)),
'market_id' => (string) $order->MarketplaceId[0],
'status'=> $order_status,
'site'=> 'AMAZON',
'last_update' => date('Y-m-d H:i:s'),
'employee_id'=>login::$id,
'addr1'=> (string) $order->ShippingAddress->AddressLine1,
'addr2'=>(string) $order->ShippingAddress->AddressLine2,
'city'=>(string) $order->ShippingAddress->City,
'state'=>(string) $order->ShippingAddress->StateOrRegion,
'zip'=>(string) $order->ShippingAddress->PostalCode,
'attention'=>(string) $order->ShippingAddress->Name,
'email'=>(string) $order->BuyerEmail,
'phone'=>$phone,
'first'=>array_shift($name), //remove the 0 element, use array shift so we can glue the rest of the array together for last name
'last'=>(implode(' ', $name)) ? implode(' ', $name): $last,
'fullname'=>(string) $order->BuyerName,
'unshipped_items'=> (string) $order->NumberOfItemsUnshipped
);
foreach ($arr as $k => $v)
$arr[$k] = strtoupper($v);
$orders[] = $arr;
}
sql::bulk_merge('dhs', 'dbo', 'orders', array('order_code', 'site'), $orders, 'id');
sql::bulk_merge('dhs', 'dbo', 'order_shipping', array('order_code', 'site'), $orders);
return $orders;
}