加快此代码的提示

时间:2009-11-20 19:03:14

标签: php mysql performance query-optimization

有人可以建议提示或更改以使此代码更清晰,更快捷吗?这是我在星期五晚上想到的唯一方法,但我确信必须有更有效的方式来做这件事......

我知道正则表达式没有效率,但我不能老实地看到我还能做到这一点,特别是如果邮政编码数据可以来自:

e1 2be e1ebe e10ebe e10 ebe ex1 ebe ex1ebe

依旧......

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

$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);

5 个答案:

答案 0 :(得分:6)

您将其发布为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。

答案 1 :(得分:2)

有些事情可能效率不高,但看起来更干净,你可以使用IN MySQL运算符:

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

答案 2 :(得分:2)

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

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.";
}

答案 3 :(得分:0)

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

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

或(psuedocode,我不是Perl人):

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

答案 4 :(得分:0)

每次遇到匹配时都不需要更新数据库。只要你做一次就足够了:

$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 == 0 true )。如果$counter的值不是0,请使用其他变量名称。

您还应该只选择您真正需要的列,在这种情况下可能是邮政编码电子邮件