亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

數據庫優化的三個例子

發布時間:2020-06-05 04:13:47 來源:網絡 閱讀:783 作者:hfhe2000 欄目:MySQL數據庫

在維護舊數據庫的時候經常碰到非常的查詢,多數都是兩方面的原因。
1)沒有加索引
2)查詢語句導致索引用不上
3)過多的連接數據庫


例子1:

在一個大型的計算中原來每天要花費半小時才能完成,對計算的過程進行仔細的分析,發現下面的語句花費了很長時間

select sum(order_qty - delivery_qty - reduce_confirm_qty - lost_qty ) qty from circle_ordering where sku = '" . $sku . "' AND submit_status = 5 AND order_type = 'AIR'

通過explain 這條語句,仔細分析數據庫才知道并沒有相關的索引作用在這條查詢語句上,這樣導致了這條sql是全表查詢。于是對這三列(sku, submit_status, order_type)新建索引. 重新執行后,整個程序只用了10份鐘就完成了。

例子2:

select a.ebay_id, b.ebay_id as ebay_subid, from_unixtime(a.ebay_paidtime) as ebay_paidtime,
                                      a.ebay_account, a.ebay_countryname, c.store_name as warehouse, a.ebay_carrier,
                                      b.sku, b.ebay_amount, a.ebay_currency, b.ebay_itemprice,
                                      b.shipingfee,  ((b.ebay_itemprice*b.ebay_amount)+b.shipingfee) as total_amount, ebay_postcode,
                                      b.item_promotion_discount_amount, b.ship_promotion_discount_amount

                                    from ebay_order a left join ebay_orderdetail b on(a.ebay_ordersn=b.ebay_ordersn) 
                                                      left join ebay_store c on (a.ebay_warehouse = c.id)
                                    where a.ebay_combine !=1 and (a.resend_org_ebay_id=0 or a.resend_org_ebay_id is null) and 
                                          b.ebay_amount >0 and a.ebay_warehouse !='' and a.ebay_user='manwei' 

                                            and                                             

                                          (

                                            a.ebay_paidtime between UNIX_TIMESTAMP('".$astart."') and UNIX_TIMESTAMP('".$aend."') 

                                            or
                                          (a.ebay_paidtime not between UNIX_TIMESTAMP('".$astart_p."') and UNIX_TIMESTAMP('".$aend_p."')  and 
                                           a.shippedtime between UNIX_TIMESTAMP('".$astart_p."') and UNIX_TIMESTAMP('".$aend_p."')) ";

                                        if($last_ebay_id!='') $data .= " or a.ebay_id >='".$last_ebay_id."'";

                                        $data .=  ") order by a.ebay_id, b.ebay_id ";

注意這個復雜的查詢語句的條件

第一個條件
(a.ebay_paidtime between UNIX_TIMESTAMP('".$astart."') and UNIX_TIMESTAMP('".$aend."')
由于在ebay_paidtime字段有索引,如果只有這個條件,查詢速度很快,查詢一次不到一秒。但是因為后面還有兩個條件使用了 or, 這樣導致會導致了對ebay_order進行了全表查詢,而這個表有3百多萬條數據,所以查詢非常慢。
(有這個說法 :驗證在兩個相同字段之間使用or不會導致全表掃描,只有出現不同字段自建使用or時會導致全表掃描。但我沒有驗證過。)

根據業務需求我們把三個用or 連接的查詢條件拆出來,分別進行查詢,最后用union語句連起來。這樣查詢的效率得到了大大的提高。修改后的查詢如下

$data1 ="select " . $fields_list . "
                                    from ebay_order a left join ebay_orderdetail b on(a.ebay_ordersn=b.ebay_ordersn) 
                                                      left join ebay_store c on (a.ebay_warehouse = c.id)
                                    where a.ebay_combine !=1 and (a.resend_org_ebay_id=0 or a.resend_org_ebay_id is null) and 
                                          b.ebay_amount >0 and a.ebay_warehouse !='' and a.ebay_user='manwei' 
                                          and  a.ebay_paidtime between UNIX_TIMESTAMP('".$astart."') and UNIX_TIMESTAMP('".$aend."')";

  $data2 = "select " . $fields_list . "
                                    from ebay_order a left join ebay_orderdetail b on(a.ebay_ordersn=b.ebay_ordersn) 
                                                      left join ebay_store c on (a.ebay_warehouse = c.id)
                                    where a.ebay_combine !=1 and (a.resend_org_ebay_id=0 or a.resend_org_ebay_id is null) and 
                                          b.ebay_amount >0 and a.ebay_warehouse !='' and a.ebay_user='manwei' 
                                          and (
                                                a.shippedtime between UNIX_TIMESTAMP('".$astart_p."') and UNIX_TIMESTAMP('".$aend_p."') and
                                                a.ebay_paidtime not between UNIX_TIMESTAMP('".$astart."') and UNIX_TIMESTAMP('".$aend."') 
                                           )";

    if($last_ebay_id!='') {
             $data3 = "select " . $fields_list . "
                                    from ebay_order a left join ebay_orderdetail b on(a.ebay_ordersn=b.ebay_ordersn) 
                                                      left join ebay_store c on (a.ebay_warehouse = c.id)
                                    where a.ebay_combine !=1 and (a.resend_org_ebay_id=0 or a.resend_org_ebay_id is null) and 
                                          b.ebay_amount >0 and a.ebay_warehouse !='' and a.ebay_user='manwei' 
                                          and a.ebay_id >='" .$last_ebay_id ."'";
   }

    $data = "(" . $data1 . ")";
  if($data2 != "") $data = $data . " union (". $data2 . ")";
  if($data3 != "") $data = $data . " union (". $data3 . ")";

小插曲,當我們分析data2的時候,無論如何給shippedtime加索引,只要查詢shippedtime都是全表查詢。仔細分析才知道原來在數據庫設計的時候,這個shippedtime的字段是varchar, 程序把時間戳保存成這種類型,自然沒有辦法使用適合我們需要的索引,解決的方法是通過alter語句先把shippedtime改成int 類型,再增加一個索引到這個字段。這樣這個查詢慢的問題就徹底得到解決了。

例子3:

$data = $isfesdb->query($data);
$quan = $isfesdb->num_rows($data);

for($i=0;$i<$quan;$i++){
{
            ...
            $vv             = "select goods_name, goods_weight from ebay_goods where goods_sn='".$sku[$i]."' limit 1";
            $vv             = $isfesdb->execute($vv);
            $vv             = $isfesdb->getResultArray($vv);

            if(count($vv)==0){                      

                            ...
                            $sku[$i]   = str_replace('-FBA-FR','',$sku[$i]);                                    
                            ...

                        }

            ...
}

從代碼上看,這個只是很簡單的查詢,ebay_goods也有索引,應該很快就能查詢到結果。但實際上整個流程跑下來很慢。仔細分析原因是因為$quan的數字太大,導致了for循環超過了10000次,這樣導致了$vv這個查詢進行了10000次。所以單獨查一條沒有性能問題,但是如果多次重復這樣的查詢就會引起性能問題。

解決的方法就是在for循環的前面先查詢ebay_goods全表,把這個表記錄到一個數組,然后在for循環里使用素組的數據。因為ebay_goods這個數組只有幾千條記錄,這個方法是可行的。
修改程序變成:

$vv = $isfesdb->query("select goods_sn, goods_name, goods_weight from ebay_goods");
$vv_quan = $isfesdb->num_rows($vv);
$vv_result = $isfesdb->getResultArray($vv);

for($i=0; $i<$vv_quan; $i++) {
        $goods_array[$vv_result[$i]['goods_sn']] = array($vv_result[$i]['goods_name'], $vv_result[$i]['goods_weight']); 
        }

for($i=0;$i<$quan;$i++)
{
...

     if(!array_key_exists($sku[$i], $goods_array)){

             ...
             $sku[$i]   = str_replace('-FBA-FR','',$sku[$i]);                                   
             ...

     }

 ...
 }

我們采用數組的方法后,查詢也比舊方法效率提高好幾倍。這是因為現在我們的服務器配置的內存是足夠大的,PHP的運行也是足夠快的。瓶頸就在于php在等待mysql的查詢結果。所以我們先用一次查詢把數據庫結果組成了數組。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

浦城县| 泗水县| 金沙县| 云梦县| 揭西县| 罗甸县| 宣威市| 广元市| 华安县| 江山市| 东乡| 丁青县| 民权县| 通河县| 达尔| 安化县| 本溪市| 紫金县| 前郭尔| 泗阳县| 嵩明县| 额敏县| 鄂伦春自治旗| 麻江县| 荔波县| 西青区| 武川县| 来凤县| 汶上县| 瑞金市| 商城县| 葫芦岛市| 崇义县| 枣强县| 渭南市| 民丰县| 益阳市| 大洼县| 会泽县| 乌海市| 昌都县|