所以首先我的MySQL表中這樣定義:MySQL的 - 花費過多時間來執行查詢
訂單(333000+記錄)
orders_id(PK),
customerName,
CompanyName,
Status,
shipping_no,
shipping_module,
tracking_no,
orders_status,
date_purchased..
ORDER_STATUS(70條記錄)
orders_status_id(pk),
language_id,
orders_status_name
orders_status_history(2220000+ r ecords)
`orders_status_history_id` int(11)
`orders_id` int(11)
`orders_status_id` int(5)
PRIMARY KEY (`orders_status_history_id`)
orders_status_history表包含每個訂單
`orders_status_id` int(11)
`orders_status_name` varchar(32)
PRIMARY KEY (`orders_status_id`,`language_id`)
那麼我試圖得到的是不同的狀態,下面這三個選項描述:
- 訂單必須有
shipping_module
pickup_pickup或pickup2_pickup2 orders_status_history.orders_status_id
必須有以下狀態7,21,34,40- 但
orders_status_history.orders_status_id
不得有下列狀態33,53
說明問題: 假設有10項目,和他們有過如下的狀態,在一些時間在其一生中:
- [7,34,41,48]
- [20,40,34,57,14,25]
- [53,7,40,5]
- [41,25,4]
- [1,2,3,4]
- [34,4,33,53,7]
- [4,21,31,7,8] 我想
- [78,15,45,40]
- [53,40,31,21,7]
- [33,74,54,7,22]
所以訂單提取是1,2,7,8-因爲這個訂單包含7,31,21或40,而不是53,33
我曾嘗試以下查詢:
1)
SELECT *
FROM orders AS o, orders_status_history AS osh
WHERE (
o.shipping_module LIKE '%pickup_pickup%'
OR o.shipping_module LIKE '%pickup2_pickup2%'
)
AND o.orders_id = osh.orders_id
AND osh.orders_status_id
IN (7, 21, 31, 40) AND osh.orders_status_id
NOT IN (33, 53)
此查詢工作正常的表現,但它得到的所有結果(1200條記錄),但它並沒有過濾3選項
2 。)
SELECT *
FROM orders AS o, orders_status_history AS osh
WHERE (
o.shipping_module LIKE '%pickup_pickup%'
OR o.shipping_module LIKE '%pickup2_pickup2%'
)
AND o.orders_id = osh.orders_id
AND osh.orders_status_id IN (7, 21, 31, 40)
AND osh.orders_status_id != 33
AND osh.orders_status_id != 53
它的工作原理也如以前,didnt過濾器3選項
3)
SELECT *
FROM orders AS o, orders_status_history AS osh
WHERE (
o.shipping_module LIKE '%pickup_pickup%'
OR o.shipping_module LIKE '%pickup2_pickup2%'
)
AND o.orders_id = osh.orders_id
AND osh.orders_status_id IN (7, 21, 31, 40)
AND osh.orders_status_id NOT IN (
SELECT so.orders_id
FROM orders AS so, orders_status_history AS sosh
WHERE (
so.shipping_module LIKE '%pickup_pickup%'
OR so.shipping_module LIKE '%pickup2_pickup2%'
)
AND sosh.orders_status_id != 33
)
這個查詢花費了太多的時間來執行,並沒有EXCUTE
4 )
SELECT *
FROM orders AS o, orders_status_history AS osh
WHERE (
o.shipping_module LIKE '%pickup_pickup%'
OR o.shipping_module LIKE '%pickup2_pickup2%'
)
AND o.orders_id = osh.orders_id
AND osh.orders_status_id = 7
AND osh.orders_status_id = 21
AND osh.orders_status_id = 31
AND osh.orders_status_id = 40
AND osh.orders_status_id != 33
AND osh.orders_status_id != 53
該查詢當先過於查詢沒有過濾選項3
所以後來我用PHP
$sql = "SELECT o.orders_id, osh.orders_status_history_id
FROM
orders AS o,
orders_status_history AS osh
WHERE (
o.shipping_module LIKE '%pickup_pickup%'
OR o.shipping_module LIKE '%pickup2_pickup2%'
)
AND o.orders_id = osh.orders_id
AND osh.orders_status_id IN (7, 21, 31, 40)
AND osh.orders_status_id != 33
AND osh.orders_status_id != 53";
$sql = mysql_query($sql);
while ($row = mysql_fetch_array($sql)){
$row["orders_id"]);
if(getOrderStatus($row["orders_id"]))
echo "<br/>".$row["orders_id"];
}
function getOrderStatus($order){
$sql = "SELECT orders_status_id FROM orders_status_history WHERE orders_id = ".$order;
echo "<br/> Sql Query : ".$sql;
$sql = mysql_query($sql);
while ($status = mysql_fetch_array($sql))
if((int)$status["orders_status_id"] == 33 || (int)$status["orders_status_id"] == 53)
return false;
return true;
}
此代碼是花費過多時間超過30m嘗試過。我set_time_limit(0);
注:我只能使用Mysql_ *因爲我們的PHP版本是4.9
除了PHP 4.9真的過時了(你應該提醒你的老闆升級),你有沒有運行'在你的查詢中解釋......'爲表格設置了什麼樣的指數? – Paul
'osh.orders_status_id IN(7,21,31,40)AND osh.orders_status_id NOT IN(33,53)''沒有任何意義,就好像某物是(7,21,31,40)而不是定義不(33,53)。其他查詢以不同的形式呈現。那麼你確定你仍然在33,53在你的resluts獲得記錄? – pawel7318
我從來沒有見過任何人使用PHP 4年...這是嚴重過時的,完全不安全。此外,它不應該影響查詢..因爲@ paul提到在查詢前面使用'EXPLAIN'。它應該,解釋它做了什麼,它使用了什麼索引......它可能缺少一些 –