加速此代码的提示

Posted

技术标签:

【中文标题】加速此代码的提示【英文标题】:Tips for speeding up this code 【发布时间】:2009-11-20 19:03:14 【问题描述】:

任何人都可以提出提示或更改以使此代码更简洁和更快吗?这是我能想到的在星期五晚上这样做的唯一方法,但我确信一定有更有效的方法......

我知道正则表达式效率不高,但老实说我不知道​​我还能如何做到这一点,特别是如果邮政编码数据可以来自以下任何内容:

e1 2be e1ebe e10ebe e10 埃贝 ex1 埃贝 ex1ebe

等等……

非常感谢任何编码提示, H

$conn = mysql_connect($dbhost, $dbuser, $dbpass) or die ('Amma Gawd! Someone ate our database!');
    mysql_select_db($dbname);
    $result = mysql_query("SELECT * FROM `Consumer`
            WHERE left(`Postcode`,2) = 'E' 
            OR left(`Postcode`,1) = 'N'
            OR left(`Postcode`,1) = 'W'");
    while($row = mysql_fetch_array($result))   
        $email =  $row['Email'];
        if (preg_match("/^[Ee]1[0-9]2/",$row['Postcode'])) 
            mysql_query("UPDATE `Consumer` SET `CONYES` = '1' WHERE `Email` = '$email'") or die ("Bugger");
            $counter = $counter +1;
         elseif (preg_match("/^[Nn]1[0-9]2/",$row['Postcode'])) 
            mysql_query("UPDATE `Consumer` SET `CONYES` = '1' WHERE `Email` = '$email'") or die ("Bugger");
            $counter = $counter +1;     
         elseif (preg_match("/^[Ww]1[0-9]2/",$row['Postcode'])) 
            mysql_query("UPDATE `Consumer` SET `CONYES` = '1' WHERE `Email` = '$email'") or die ("Bugger");
            $counter = $counter +1; 
           
    

    $result1 = mysql_query("SELECT * FROM `Consumer`
            WHERE left(`postcode`,2) = 'BR' 
            OR left(`postcode`,2) = 'CR'
            OR left(`postcode`,2) = 'EC'
            OR left(`postcode`,2) = 'EN'
            OR left(`postcode`,2) = 'KT'
            OR left(`postcode`,2) = 'NW'
            OR left(`postcode`,2) = 'RM'
            OR left(`postcode`,2) = 'SE'
            OR left(`postcode`,2) = 'SM'
            OR left(`postcode`,2) = 'SW'
            OR left(`postcode`,2) = 'TW'
            OR left(`postcode`,2) = 'WC'
            OR left(`postcode`,2) = 'BD'
            OR left(`postcode`,2) = 'HG'
            OR left(`postcode`,2) = 'LS'
            OR left(`postcode`,2) = 'WF'
            OR left(`postcode`,2) = 'YO'
            OR left(`postcode`,2) = 'HD'
            OR left(`postcode`,2) = 'HX'");
    while($row1 = mysql_fetch_array($result1))     
        $email =  $row1['Email'];
        mysql_query("UPDATE `Consumer` SET `CONYES` = '1' WHERE `Email` = '$email'") or die ("Bugger");
        $counter = $counter +1; 
    
    echo $counter;
    mysql_close($conn);

【问题讨论】:

left(Postcode,2) = 'E'?未离开(Postcode,1) = 'E'? @Mark Byers - 很好发现,是的,这是一个错误! 我认为您的以 W 或 B 开头的邮政编码也不会被看到,因为它们不会在初始查询中存活下来。您缺少两行:OR left(Postcode,1) = 'W' OR left(Postcode,1) = 'B'。 抱歉,应该是 M,而不是 W。 这正是为什么我不应该在星期五晚上 7 点编码 - 只需要找到 ENW,其他 if 语句是多余的^^ 【参考方案1】:

您将它作为一个 php 问题发布,但我认为最有效的方法是在一个 SQL 查询中完成所有操作并让数据库完成这项工作。您可以使用关键字 'RLIKE' 让数据库执行正则表达式匹配。您应该阅读语法以获得您想要的确切内容,但只是为了让您开始,您需要这样的东西:

UPDATE `Consumer` SET `CONYES` = '1'
    WHERE `Postcode` RLIKE '[EeNnWwBbMm][0-9]2'
    OR LEFT(`postcode`,2) IN ('BR', 'CR', 'EC', 'EN', 'KT', 'NW', 'RM'.....

结果是改变的行数,可以直接赋值给$counter。

【讨论】:

【参考方案2】:

可能不是更有效,但看起来更干净,您可以使用IN MySQL 运算符:

SELECT * FROM `Consumer` WHERE left(`postcode`,2) IN ('BR', 'CR', 'EC', 'EN', 'KT', 'NW', 'RM'.....

【讨论】:

【参考方案3】:

示例代码看起来等同于单个查询:

UPDATE `Consumer` SET `CONYES` = 1
   WHERE  Email IS NOT NULL 
     AND Postcode RLIKE '^([NEW][0-9]2|B[DR]|CR|E[CN]|H[DGX]|KT|LS|[NT]W|RM|S[EMW]|W[CF]|YO)'

RE 的可读性不如“IN”运算符,但性能可能更高。可能会有更合适、更宽松、更正确的正则表达式;之所以选择上述内容,是因为它与示例中的内容相同。您唯一需要做的另一件事是获取受影响的行数,使用PDO 很容易做到(无论如何,您应该使用它而不是旧的 MySQL 驱动程序):

try 
    $db = new PDO("mysql:host=$dbhost,dbname=$dbname", $dbuser, $dbpass);
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $count = $db->exec("UPDATE `Consumer` SET `CONYES` = 1
       WHERE  Email IS NOT NULL 
         AND Postcode RLIKE '^([NEW][0-9]2|B[DR]|CR|E[CN]|H[DGX]|KT|LS|[NT]W|RM|S[EMW]|W[CF]|YO)'"
    );
    echo $count;
 catch (PDOException $exc) 
    // handle exception as you will
    error_log($exc);
    echo "I had an internal error. It's been logged, and we'll look into it.";

【讨论】:

【参考方案4】:

您可以尝试匹配补码,并在不匹配的所有内容上设置 CONYES = '1'。也许这是一个更容易的决定,例如:

select * from Consumer where left(postcode, 2) <> 'XX'

或者(伪代码,我不是 Perl 人):

if (!preg_match(complementRegexString, $row['Postcode'])
    mysql_query("UPDATE `Consumer` SET `CONYES` = '1' WHERE `Email` = '$email'") or die ("Bugger");

【讨论】:

【参考方案5】:

您无需在每次遇到匹配时都更新数据库。如果你只做一次就足够了:

$conn = mysql_connect($dbhost, $dbuser, $dbpass) or die ('Amma Gawd! Someone ate our database!');
mysql_select_db($dbname);
$result = mysql_query("
    SELECT `Postcode`, `Email`
    FROM `Consumer`
    WHERE LEFT(`Postcode`,1) IN ('E', 'N', 'W'");
$counter = 0;
while ($row = mysql_fetch_array($result)) 
    if (preg_match("/^[ENB][0-9]2/i",$row['Postcode'])) 
        if (!$counter) 
            $email =  $row['Email'];
            mysql_query("UPDATE `Consumer` SET `CONYES` = '1' WHERE `Email` = '$email'") or die ("Bugger");
        
        ++$counter;
    


$result = mysql_query("
    SELECT `Postcode`, `Email`
    FROM `Consumer`
    WHERE LEFT(`Postcode`, 2) IN ('BR', 'CR', 'EC', 'EN', 'KT', 'NW', 'RM', 'SE', 'SM', 'SW', 'TW', 'WC', 'BD', 'HG', 'LS', 'WF', 'YO', 'HD', 'HX')");
while ($row = mysql_fetch_array($result)) 
    if (!$counter) 
        $email = $row['Email'];
        mysql_query("UPDATE `Consumer` SET `CONYES` = '1' WHERE `Email` = '$email'") or die ("Bugger");
    
    ++$counter;

echo $counter;
mysql_close($conn);

这里的数据库只有在还没有更新的情况下才会更新(如果$counter == 0true)。如果$counter 的值不是0,请使用不同的变量名。

您还应该只选择您真正需要的列,在这种情况下可能是 PostcodeEmail

【讨论】:

以上是关于加速此代码的提示的主要内容,如果未能解决你的问题,请参考以下文章

加速此代码 - PHP/SQL - 短代码,但目前需要非常长的时间

apnetwork加速器怎么用

我无法在 api 级别 15 进行硬件加速

Win7安装魔兽争霸3后打不开提示“不能初始化DirectX”怎么办

加速度计到相对位置

在原始加速度数据上使用 PyKalman 计算位置