加速此代码的提示
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 == 0
为true)。如果$counter
的值不是0
,请使用不同的变量名。
您还应该只选择您真正需要的列,在这种情况下可能是 Postcode 和 Email。
【讨论】:
以上是关于加速此代码的提示的主要内容,如果未能解决你的问题,请参考以下文章
加速此代码 - PHP/SQL - 短代码,但目前需要非常长的时间