v2.5.2
Giriş yap

Php sorgu hızlandırma

Anonim
613 defa görüntülendi

Merhaba, aşağıda bulunan kod yapısını sorgu hızı bakımından nasıl kısaltılabilir veya hızlandırılabilir ?


  $detail = $this->connect->query("SELECT ES.orderId,ES.totalDiscount,ES.totalPrice,ES.orderDate,ES.PackageStatus,ES.Platform,ES.orderStatus,EC.customerfullName as customerNameSurname,(SELECT count(customerfullName) from entg_sales_customer where customerfullName=customerNameSurname) customerOrderCount FROM entg_sales ES LEFT JOIN entg_sales_customer EC ON ES.orderId = EC.orderId and ES.auth = EC.auth WHERE ES.orderDate BETWEEN '$orderDate' AND '$orderEndDate' AND (ES.auth = '$this->appkey' and ES.orderStatus='$orderStatus') ORDER BY ES.id DESC");
            $rowPD = $detail->rowCount();
            $orderList = [];
            if ($rowPD > 0) {
                $detail = $detail->fetchAll(PDO::FETCH_ASSOC);
                foreach ($detail as $keys) {
                    $orderId = $keys["orderId"];
                    $detail = $this->connect->query("select orderId,packageId,totalDiscount,totalPrice,orderDate,agreedDeliveryDate,Platform,orderStatus from entg_sales where orderId='$orderId' and auth='$this->appkey'")->fetch(PDO::FETCH_ASSOC);
                    $adress = $this->connect->query("select firstName,lastName,fullName,address,city,district,type,fullAddress from entg_sales_adress where orderId='$orderId' and auth='$this->appkey'")->fetchAll(PDO::FETCH_ASSOC);
                    $cargoDetail = $this->connect->query("SELECT cargoTrackingNumber,cargoProviderName,cargoPrice FROM entg_sales_cargo where orderId='$orderId' and auth='$this->appkey'")->fetch(PDO::FETCH_ASSOC);
                    $customerDetail = $this->connect->query("SELECT customerFirstName,customerLastName,customerEmail,customerFullName,tcIdentityNumber,taxOffice,taxId FROM entg_sales_customer where orderId='$orderId' and auth='$this->appkey'")->fetch(PDO::FETCH_ASSOC);
                    $list = $this->connect->query("SELECT ESD.barcode, ESD.productName, ESD.productCode, ESD.merchantCode, ESD.productSize, ESD.quantity, ESD.amount, ESD.discount, ESD.price, ESD.attributeValue, ESD.Tax, ESD.salesCampaignId, EP.barcode, PM.imageName, P.purchase, P.purchaseTax, P.discount1, P.discount2, P.discount3, P.tax FROM entg_sales_detail ESD LEFT JOIN entg_product EP ON ESD.barcode = EP.barcode AND ESD.auth = EP.auth LEFT JOIN product_images PM ON EP.mainBarcode = PM.barcode AND EP.auth = PM.auth LEFT JOIN product P ON P.barcode = PM.barcode AND P.auth = PM.auth WHERE ESD.orderId = '$orderId' AND ESD.auth = '$this->appkey' GROUP BY EP.mainBarcode")->fetchAll(PDO::FETCH_ASSOC);
                    $orderJson = [
                        "detail" => $detail,
                        "adress" => $adress,
                        "cargoDetail" => $cargoDetail,
                        "customerDetail" => $customerDetail,
                        "list" => $list
                    ];
                    $orderList[] = $orderJson;
                }
            } 

Cevap yaz
Cevaplar (3)
ebykdrms
783 gün önce

Bir kez daha bakınca aslında daha kısa SQL oluşmasını sağlayabilirmişiz gibi göründü.
Mesela ilk foreach döngüsünde oluşturup $whereCondition değişkenine atadığımız string örnek olarak şöyle:
(orderId='123' auth='abc') OR (orderId='131' auth='abc') OR (orderId='213' auth='abc')
yani aslında auth sütunu hep aynı. O halde bunu tek bir AND ifadesiyle birleştirebilirdik. Yani:
auth='abc' AND (orderId='123' OR orderId='131' OR orderId='213')
şeklinde yazabilirdik. Muhtemelen az da olsa MySQL için de daha rahat bir sorgu olacaktır. İki sütunu her OR bloğu için kontrol etmemiş olur.
Bu durumda aşağıdaki şu satırları:

foreach ($detail as $keys) {
    $whereConditions[] = "(orderId='" . $keys["orderId"] . "' AND auth='" . $this->appkey . "')";
    $whereConditionsWithESD[] = "(ESD.orderId='" . $keys["orderId"] . "' AND ESD.auth='" . $this->appkey . "')";
}
$whereCondition = implode(" OR ", $whereConditions);
$whereConditionWithESD = implode(" OR ", $whereConditionsWithESD);

şu şekilde değiştirmek daha yerinde olur:

foreach ($detail as $keys) {
    $orderId = $keys["orderId"];
    $whereConditions[] = "orderId='$orderId'";
    $whereConditionsWithESD[] = "ESD.orderId='$orderId'";
}
$whereCondition = implode(" OR ", $whereConditions);
$whereConditionWithESD = implode(" OR ", $whereConditionsWithESD);

$appKey = $this->appkey;
$whereCondition = "auth='$appKey' AND ($whereCondition)";
$whereConditionWithESD = "ESD.auth='$appKey' AND ($whereCondition)";

Böylece satır sayısı biraz arttı ama MySQL için daha rahat bir sorgu oluşturduk.

Aşağıdaki satırlarda sanırım $orderList objesindeki değer kodunuzdaki diğer kurgularla uyuşmadığı için yeni bir formata çevirerek orderId değerlerine göre gruplamışsınız.
O kısmı şu şekilde değiştirirseniz daha kısa kodla işi çözebilirsiniz sanıyorum.
Yani yukarıdaki kodlardan sonra gelen kodlarınızdaki $orderListESD = []; ile başlayıp $orderList = $orderListESD; ile biten kısmı komple silip yerine şunu yazabilirsiniz:

$relationalOrderList = [];
foreach($orderList["detail"] as $detail) {
    $orderId = $detail["orderId"];
    $relationalOrderList[] = [
        "detail" => $detail,
        "address" => array_filter($orderList["address"], function($item){ return $item["orderId"]===$orderId; }),
        "cargoDetail" => array_filter($orderList["cargoDetail"], function($item){ return $item["orderId"]===$orderId; }),
        "customerDetail" => array_filter($orderList["customerDetail"], function($item){ return $item["orderId"]===$orderId; }),
        "list" => array_filter($orderList["list"], function($item){ return $item["orderId"]===$orderId; }),
    ];
}
$orderList = $relationalOrderList;
polev
784 gün önce

Aşağıdaki gibi düzeltme sağladım şuanlık sağlıklı çalışıyor sizinde görüşünüzü almak isterim @ebykdrms

$detail = $this->connect->query("SELECT * FROM entg_sales WHERE orderDate BETWEEN '$orderDate' AND '$orderEndDate' AND (auth = '$this->appkey' and orderStatus='$orderStatus') ORDER BY id DESC");
            $rowPD = $detail->rowCount();
            $orderList = [];
            $whereConditions = [];
            $whereConditionsWithESD = [];
            if ($rowPD > 0) {
                $detail = $detail->fetchAll(PDO::FETCH_ASSOC);
                foreach ($detail as $keys) {
                    $whereConditions[] = "(orderId='" . $keys["orderId"] . "' AND auth='" . $this->appkey . "')";
                    $whereConditionsWithESD[] = "(ESD.orderId='" . $keys["orderId"] . "' AND ESD.auth='" . $this->appkey . "')";
                }
                $whereCondition = implode(" OR ", $whereConditions);
                $whereConditionWithESD = implode(" OR ", $whereConditionsWithESD);
                $detail = $this->connect->query("select orderId,packageId,totalDiscount,totalPrice,orderDate,agreedDeliveryDate,Platform,orderStatus from entg_sales WHERE $whereCondition")->fetchAll(PDO::FETCH_ASSOC);
                $adress = $this->connect->query("select orderId,firstName,lastName,fullName,address,city,district,type,fullAddress from entg_sales_adress WHERE $whereCondition")->fetchAll(PDO::FETCH_ASSOC);
                $cargoDetail = $this->connect->query("SELECT orderId,cargoTrackingNumber,cargoProviderName,cargoPrice FROM entg_sales_cargo WHERE $whereCondition")->fetchAll(PDO::FETCH_ASSOC);
                $customerDetail = $this->connect->query("SELECT orderId,customerFirstName,customerLastName,customerEmail,customerFullName,tcIdentityNumber,taxOffice,taxId FROM entg_sales_customer WHERE $whereCondition")->fetchAll(PDO::FETCH_ASSOC);
                $list = $this->connect->query("SELECT ESD.orderId,ESD.barcode, ESD.productName, ESD.productCode, ESD.merchantCode, ESD.productSize, ESD.quantity, ESD.amount, ESD.discount, ESD.price, ESD.attributeValue, ESD.Tax, ESD.salesCampaignId, EP.barcode, P.barcode, ( SELECT imageName FROM product_images WHERE barcode = P.barcode ORDER BY imageName DESC LIMIT 1 ) AS imageName, P.purchase, P.purchaseTax, P.discount1, P.discount2, P.discount3, P.tax FROM entg_sales_detail ESD LEFT JOIN entg_product EP ON ESD.barcode = EP.barcode AND ESD.auth = EP.auth LEFT JOIN product_images PM ON EP.mainBarcode = PM.barcode AND EP.auth = PM.auth LEFT JOIN product P ON P.barcode = PM.barcode AND P.auth = PM.auth WHERE $whereConditionWithESD GROUP BY ESD.barcode ORDER BY imageName ASC")->fetchAll(PDO::FETCH_ASSOC);
                $orderList = [
                    "detail" => $detail,
                    "adress" => $adress,
                    "cargoDetail" => $cargoDetail,
                    "customerDetail" => $customerDetail,
                    "list" => $list
                ];
                $orderListESD = [];
                foreach ($orderList["detail"] as $detail) {
                    $array = [
                        "detail" => $detail,
                        "adress" => array(),
                        "cargoDetail" => [],
                        "customerDetail" => [],
                        "list" => array()
                    ];
                    foreach ($orderList["adress"] as $adress) {
                        if ($detail["orderId"] == $adress["orderId"]) {
                            array_push($array["adress"], $adress);
                        }
                    }
                    foreach ($orderList["cargoDetail"] as $cargoDetail) {
                        if ($detail["orderId"] == $cargoDetail["orderId"]) {
                           $array["cargoDetail"] = $cargoDetail;
                        }
                    }
                    foreach ($orderList["customerDetail"] as $customerDetail) {
                        if ($detail["orderId"] == $customerDetail["orderId"]) {
                            $array["customerDetail"] = $customerDetail;
                        }
                    }
                    foreach ($orderList["list"] as $list) {
                        if ($detail["orderId"] == $list["orderId"]) {
                            array_push($array["list"], $list);
                        }
                    }
                    $orderListESD[] = $array;
                }
                $orderList = $orderListESD;
            } 
ebykdrms
787 gün önce

foreach içinde sql sorgusu atmamalısınız.
Hepsinde ortak olan sanırım orderId ve auth sütunları.
İlk sorgunuzdan sonra bu orderId ve auth değerlerini bir string içinde birleştirin ve or'larla birbirine bağlayın.

$detail = $this->connect->query("...");
$rowPD = $detail->rowCount();
$orderList = [];
$whereConditions = [];
$whereConditionsWithESD = [];
if ($rowPD > 0) {
    $detail = $detail->fetchAll(PDO::FETCH_ASSOC);
    foreach ($detail as $keys) {
        $whereConditions[] = "(orderId='".$keys["orderId"]."' AND auth='".$this->appkey."')";
        $whereConditionsWithESD[] = "(ESD.orderId='".$keys["orderId"]."' AND ESD.auth='".$this->appkey."')";
    }
    $whereCondition = implode(" OR ", $whereConditions);
    $whereConditionWithESD = implode(" OR ", $whereConditionsWithESD);
    
    $detail = $this->connect->query("... WHERE $whereCondition")->fetch(PDO::FETCH_ASSOC);
    $adress = $this->connect->query("... WHERE $whereCondition")->fetchAll(PDO::FETCH_ASSOC);
    $cargoDetail = $this->connect->query("... WHERE $whereCondition")->fetch(PDO::FETCH_ASSOC);
    $customerDetail = $this->connect->query("... WHERE $whereCondition")->fetch(PDO::FETCH_ASSOC);
    $list = $this->connect->query("... WHERE $whereConditionWithESD ...")->fetchAll(PDO::FETCH_ASSOC);
    $orderList = [
        "detail" => $detail,
        "adress" => $adress,
        "cargoDetail" => $cargoDetail,
        "customerDetail" => $customerDetail,
        "list" => $list
    ];
}

Sorgularınızın içeriğini bilmiyorum ama hepsinin WHERE koşulu aynı. sadece WHERE koşullarını yukarıdaki gibi düzenleyebilirsiniz.
Örneğin foreach içindeki ilk 4 sorgunuzdaki
where orderId='$orderId' and auth='$this->appkey'
yerine
WHERE $whereCondition yazacaksınız.
$list için olan son sorguda da
WHERE ESD.orderId = '$orderId' AND ESD.auth = '$this->appkey'
yerine
WHERE $whereConditionWithESD yazacaksınız.

Böylece mesela $detail için her foreach döngüsünde
WHERE orderId='123' auth='abc',
WHERE orderId='131' auth='abc',
WHERE orderId='213' auth='abc' şeklinde yazıp istek atmadık da,
tek bir $detail sorgusu için
WHERE (orderId='123' auth='abc') OR (orderId='131' auth='abc') OR (orderId='213' auth='abc')
şeklinde istek attık.

Yani mesela ilk sorgunuzdan 3 tane orderId döndüyse
foreach içindeki 5 sorgunuz 3 defa çalışacak ve MySQL'e 15 defa istek atacaksınız.
Yeni durumdaysa kaç tane orderId olursa olsun MySQL'e sadece 6 istek atacaksınız.
Veritabanına mümkün olduğunca az istek atılmalı. Bu işlem tek başına daha hızlı sonuç almanızı sağlayacaktır.
Eğer $list sorgunuzda olduğu gibi diğer sorguları da tek sorguda birleştirme şansınız varsa çok daha iyi sonuç alırsınız.
MySQL ile mümkün olduğunca az bağlantı kurmalısınız.

NOT: bu işlem sonunca var_dump() ile $orderList değişkeninizi kontrol etmeniz gerekiyor. Çünkü sizin aldığınız json formatıyla bu yeni json formatı artık farklı. Ama her iki durumda da veritabanındaki aynı değerler artık elinizde.