【问题标题】:PHP Script: How to optimizePHP 脚本:如何优化
【发布时间】:2017-03-20 06:04:09
【问题描述】:

我为 wordpress 插件编写了一个脚本。这个 wordpress 插件处理从 XML 文件到产品的导入。因为插件通常会用新值覆盖现有产品,所以我添加了一些自定义代码来添加新产品信息,而不是覆盖它们。

第一个问题是我“内存耗尽”,因为我使用了一些其他插件方法,这些方法调用了 wordpress 查询等等。所以我解决了这个问题,现在我直接使用 SQL 查询而不是调用函数,函数调用查询等等......

但现在我遇到了另一个问题。代码正在运行。一切都出现并设置在它应该在的地方! 但是现在脚本正在减慢整个进度..要么我的 Ram 筋疲力尽,要么我的 SQL 数据库......所以我应该优化我的代码。

我已经看了两遍,但在我看来,我调用和保存的所有内容都是必要的...有谁知道我可以如何优化我的插件?

function wp_all_import_before_xml_import($import_id){

    if($import_id !== 72 || $import_id !== 88){

        unlink("wp_all_import.txt");

        //Datenbankverbindung aufbbauen
        $database = new mysqli("localhost", "wordpress_dc", "censored", "wordpress_5");
        $database_gk = new mysqli("localhost", "wordpress_8", "censored", "wordpress_6");

        //Datenbankverbindung checken
        if($database->connect_errno){
            $myfile = fopen("wp_all_import.txt", "a");
            fwrite($myfile, "+++Couldn't connect to database!+++\n\n");
            fclose($myfile);
        }

        if($database_gk->connect_errno){
            $myfile = fopen("wp_all_import.txt", "a");
            fwrite($myfile, "+++Couldn't connect to database!+++\n\n");
            fclose($myfile);
        }

        //WP_ALL_IMPORT Tabelleninhalt löschen
        $sql = 'DELETE FROM `wp_all_import`';
        $database->query($sql);

        //Holen alle Posts
        $values_gkw = $database_gk->query("SELECT `ID` FROM `fWR6qIN_posts` where post_type = 'product' AND post_status = 'publish'");

        while($row = $values_gkw->fetch_assoc()){
            $id = $row["ID"];
            $pid = $id;
            $title = get_the_title($pid);

            $repeater = $database_gk->query("SELECT Count(meta_key) AS cnt FROM `fWR6qIN_postmeta` Where meta_key like 'product_shops_%_price' AND (post_id = $pid)");

            while($row = $repeater->fetch_assoc()){
                $count = $row["cnt"];
            }

            for($i = 0; $i < $count; $i++){
                $price_meta = "product_shops_".$i."_price";
                $price_old_meta = "product_shops_".$i."_price_old";
                $link_meta = "product_shops_".$i."_link";
                $shop_meta = "product_shops_".$i."_shop";

                $price;
                $price_old;
                $link;
                $shop;

                $details = $database_gk->query("SELECT `meta_key`, `meta_value` FROM `fWR6qIN_postmeta` WHERE post_id = '$pid' AND (meta_key like '$price_meta' OR meta_key like '$price_old_meta' OR meta_key like '$link_meta' OR meta_key like '$shop_meta')");

                while($row_meta = $details->fetch_assoc()){
                    if($row_meta["meta_key"] == $price_meta){
                        $price = $row_meta["meta_value"];
                    }elseif($row_meta["meta_key"] == $price_old_meta){
                        $price_old = $row_meta["meta_value"];
                    }elseif($row_meta["meta_key"] == $link_meta){
                        $link = $row_meta["meta_value"];
                    }elseif($row_meta["meta_key"] == $shop_meta){
                        $shop = $row_meta["meta_value"];
                    }else{
                        $myfile = fopen("wp_all_import.txt", "a");
                        fwrite($myfile, "Is not matching!\n");
                        fclose($myfile);
                    }
                }

                //Checken ob Product Shop Row noch in Datenbank vorhanden
                $values = $database->query("SELECT * FROM `wp_all_import_xml` WHERE name = '$title' AND price = '$price' AND shop = '$shop' AND url = '$link'");

                $count_values = mysqli_num_rows($values);

                //Falls nein, lösche diese Product Shop Row aus Datenbank
                //Falls ja, füge Product Shop Row der "echten" Datenbank hinzu
                if($count_values == 0){
                    $sql = "DELETE FROM `wp_all_import` WHERE pid = '$pid' AND shop = '$shop' AND price = '$price' AND link = '$link'";
                    $database->query($sql);

                    /*
                    $myfile = fopen("wp_all_import.txt", "a");
                    fwrite($myfile, "Would delete! " . $pid . " Preis: " . $price . " Link: " . $link . "\n");
                    fclose($myfile);
                    */

                }elseif($count_values == 1){
                    $sql = "INSERT INTO `wp_all_import` (pid, price, price_old, link, shop) VALUES ('$pid', '$price', '$price_old', '$link', '$shop')";

                    if($database->query($sql) === TRUE){

                    }else{
                        $myfile = fopen("wp_all_import.txt", "a");
                        fwrite($myfile, "Product ERROR!\n");
                        fclose($myfile);
                    }

                    /*
                    $myfile = fopen("wp_all_import.txt", "a");
                    fwrite($myfile, "Would insert! " . $pid . " Preis: " . $price . " Link: " . $link . "\n");
                    fclose($myfile);
                    */

                }else{
                    $myfile = fopen("wp_all_import.txt", "a");
                    fwrite($myfile, "ERROR by detecting Product (More than 1 Row return by SQL!): " .$title. " Preis: " .$price. " Shop: " .$shop. " Link: " .$link. "\t num_rows: " .$count_values. "\n\n");
                    fclose($myfile);
                }

                $price = null;
                $price_old = null;
                $link = null;
                $shop = null;
                $price_meta = null;
                $price_old_meta = null;
                $link_meta = null;
                $shop_meta = null;

            }

            $title = null;
            $count = null;
        }
    }   
}

function my_saved_post($pid, $xml_node){
    $title = get_the_title($pid);

    if($title != "End of Import" || $title !== "Start of Import" || $title !== "Start of Import1" || $title !== "Start of Import2" || $title !== "Start of Import3" || $title !== "Start of Import4" || $title !== "Start of Import5"){

        //Datenbankverbindung aufbbauen
        $database = new mysqli("localhost", "wordpress_dc", "Q037u_PnMf", "wordpress_5");
        $title = get_the_title($pid);

        //Datenbankverbindung checken
        if($database->connect_errno){
            $myfile = fopen("wp_all_import.txt", "a");
            fwrite($myfile, "+++Couldn't connect to database!+++\n\n");
            fclose($myfile);
        }

        //Anzahl an an Product Shop Rows holen
        $aktueller_counter = -1;
        while(have_rows('product_shops', $pid)): the_row();
            $aktueller_counter = $aktueller_counter + 1;
        endwhile;

        if($aktueller_counter == -1){
            $aktueller_counter = 0;
        }   

        $pic = get_field("product_gallery_external_0_url", $pid);
        $alt = get_field("product_gallery_external_0_alt", $pid); 

        delete_row('product_gallery_external', 1, $pid);

        if($pic != null && $alt != null){
            update_post_meta($pid, 'fifu_image_url', $pic);
            update_post_meta($pid, 'fifu_image_alt', $alt);
        }

        //Preis, Alter Preis, Link und Shop holen
        $price = get_field("product_shops_0_price", $pid);
        $price_old = get_field("product_shops_0_price_old", $pid);
        $link = get_field("product_shops_0_link", $pid);
        $shop = get_field("product_shops_0_shop", $pid)->ID;


        //Holen Preis, Alten Preis, Link und Shop aus "echter" Datenbenk, wo PID = PID Und Shop = Shop
        $value = $database->query("SELECT `price`, `price_old`, `link`, `shop` FROM `wp_all_import` WHERE pid = '$pid' AND shop = '$shop' AND link = '$link'");
        $count_values = mysqli_num_rows($values);

        //Itterieren über Rückgabewert(e) der Datenbank
        while($row = $value->fetch_assoc()){
            //Wenn Shop = Shop und Preis oder Alter Preis haben sich geändert, dann lösche Eintrag aus der "echten" Datenbank, wo PID = PID, SHOP = SHOP und PREIS = PREIS (Könnten mehere Sein!)
            //Anschließend füge neuen Wert in Dantenbank ein
            if($row["shop"] == $shop && $row["link"] == $link && ($row["price"] != $price || $row["price_old"] != $price_old)){

                $rprice = $row["price"];
                $rprice_old = $row["price_old"];
                $rshop = $row["shop"];

                $sql = "DELETE FROM `wp_all_import` WHERE pid = '$pid' AND shop = '$rshop' AND price = '$rprice'";
                $database->query($sql);

                $sql = "INSERT INTO `wp_all_import` (pid, price, price_old, link, shop) VALUES ('$pid', '$rprice', '$rprice_old', '$link', '$rshop')";
                $database->query($sql);
            }
        }

        //Holen Preis, Alten Preis, Link und Shop aus "echter" Datenbenk, wo PID = PID
        $values = $database->query("SELECT `price`, `price_old`, `link`, `shop` FROM `wp_all_import` WHERE pid = '$pid'");
        $count_values = mysqli_num_rows($values);

        //Itterieren über Rückgabewert(e) der Datenbank
        while($row = $values->fetch_assoc()) {
            $row = array(
                'price' => $row["price"],
                'price_old' => $row["price_old"],
                'currency' => 'euro',
                'portal' => '',
                'link' => $row["link"],
                'shop' => $row["shop"]
            );

            //Wenn ungleich Preis = Preis, Alter Preis = Alter Preis, Link = Link und Shop = Shop, dann füge Row hinzu, da nicht gerade hinzugefügte Row aus Import und Import hat alle Product Shop Rows gelöscht

            //Ansonsten füge Eintrag in Datenbank ein, da eben neu hinzugefügt durch Import
            if(!($row["price"] == $price && $row["price_old"] == $price_old && $row["link"] == $link && $row["shop"] == $shop)){
                $j = add_row('product_shops', $row, $pid);
            }else{
                $sql = "INSERT INTO `wp_all_import` (pid, price, price_old, link, shop) VALUES ('$pid', '$price', '$price_old', '$link', '$shop')";
                $database->query($sql);
            }
        }
    }
}

您好,谢谢!

【问题讨论】:

  • 在循环中执行 MySQL 查询通常是个坏主意,并且可能是导致运行缓慢的罪魁祸首。看看事务,这也将帮助您保持数据完整性,因为如果您在脚本中途遇到错误,您可以恢复对数据库的更改,而不必担心它处于损坏状态。请参阅此处的 MySQL 文档:dev.mysql.com/doc/refman/5.7/en/commit.html 编辑:看起来您正在使用 fopen 和 fwrite 做类似的事情。要将多行附加到文件中,您应该在循环中构建字符串,然后向文件写入一次
  • 如果出现问题,我只是在文件中写入一些内容。但实际上没有任何问题。所以这不应该是目前的错误......

标签: php mysql wordpress optimization ram


【解决方案1】:

效率极低:

$array = SELECT ...;
foreach ($array as $item)
{
    do some SQL with $item
}

相反,如果可以一次完成所有工作,请寻找一种方法。例子:

INSERT INTO ... SELECT ...,

DELETE FROM a JOIN b ON ... WHERE ...

可以改进:

DELETE a row
INSERT replacement for that row

改为:

INSERT ... ON DUPLICATE KEY UPDATE ...

一定要有合适的

UNIQUE(pid, shop, price)

这样它就知道你在“更新”哪一行。

您提到了 XML 并且内存不足?我没有看到任何 XML 函数? XML 可能会占用大量内存。

您应该在每个query() 之后检查错误。

我希望您每次运行不会重新连接多次。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-13
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 2014-02-05
    • 2023-03-17
    • 2016-09-13
    • 1970-01-01
    相关资源
    最近更新 更多