脚本太慢,mysql加入?
Posted
技术标签:
【中文标题】脚本太慢,mysql加入?【英文标题】:Script too slow, mysql join? 【发布时间】:2011-03-17 12:52:00 【问题描述】:我正在编写一个带有产品过滤器的脚本。一切正常,但速度太慢。原因是查询太多。 Query5 选择大约 200 个条目。 Query12 在 130.000 个条目中“搜索”。
是否可以使用更少的查询来进行 mysql 连接或更快的连接?
<?php
$query5 = mysql_query("SELECT id,fabrikant,naam FROM producten_new WHERE icecat_cat='".secure_in($obj->icecat)."'".$selecteren."");
while($row5 = mysql_fetch_assoc($query5))
foreach($_GET as $key=>$value)
if($key != "p" AND $key != "id" AND $key != "merk" AND $key != "submit" AND $value != "0")
$query12 = mysql_query("SELECT COUNT(id) as aantal FROM producten_specs WHERE name='".secure_in(str_replace("_", " ", $key))."' AND value='".secure_in($value)."' AND product_id='".secure_in($row5['id'])."'");
$data12 = mysql_fetch_assoc($query12);
if($data12['aantal'])
$product_present = TRUE;
else
$product_present = FALSE;
break;
if($product_present)
echo $row5['id']."<br />";
$product_present = FALSE;
?>
谢谢。
编辑: 好的,重新开始。我希望这样更好(更快):
//Select products from category and brand
$query5 = mysql_query("SELECT id FROM producten_new WHERE icecat_cat='".secure_in($obj->icecat)."'".$selecteren."");
while($row5 = mysql_fetch_assoc($query5))
$query5_ids .= $row5['id'].", ";
//Remove last ','
$query5_ids = substr($query5_ids, 0, -2);
//Get all $_GET's
foreach($_GET as $key=>$value)
if($key != "p" AND $key != "id" AND $key != "merk" AND $key != "submit" AND $value != "0")
$specs_gets .= $key.",".$value.";";
$count_gets++;
$selection .= "name='".secure_in(str_replace("_", " ", $key))."' AND value='".secure_in($value)."' OR ";
//Remove last ';'
$specs_gets = substr($specs_gets, 0, -1);
//$selection = " AND ".substr($selection, 0, -4);
$selection = substr($selection, 0, -4);
//THE query..
//$query12 = mysql_query("SELECT product_id FROM producten_specs WHERE product_id IN ('".secure_in($query5_ids)."') ".$selection." ORDER BY product_id ASC");
$query12 = mysql_query("SELECT product_id FROM producten_specs WHERE ".$selection." ORDER BY product_id ASC");
while($row12 = mysql_fetch_assoc($query12))
if($product_hold == $row12['product_id'])
$product_hold_count++;
else
$product_hold_count = FALSE;
$product_hold = $row12['product_id'];
$product_hold_count = 1;
if($product_hold_count == $count_gets)
$query12_ids_ok .= $row12['product_id'].", ";
$count_products++;
//Remove last ','
$query12_ids_ok = substr($query12_ids_ok, 0, -2);
EDIT2 网站链接:snip
EDIT3 更多信息:
网址示例:
index.php
?p=categorie
&id=5
&brand=Asus
&Display_inch=0
&Resolution=0
&Buldin_camera=0
&Chipset=0
&Processor-speed=2400+MHz
&Processorfamilie=0
&Hard+disk-interface=0
&Total+capacitie=500+GB
*snip (because its very long)*
&submit=Submit+Filter
数据库:
product_new(包含 3500 个条目)- 包含一般产品信息
id、供应商、价格、icecat_cat、名称等
1、华硕、500、笔记本、K72F
product_specs(包含 130.000 个条目)- Contians 产品规格
id、product_id、cat、name、value
1、1,处理器,处理器速度,2400 Mhz
2、1、硬盘、总容量、500 GB
EDIT4 我越来越近了,请参阅我第一次编辑中的代码,只有 product_id IN ('".secure_in($query5_ids)."') 必须添加到 query12 中。然后我得到了我想要的结果,而且速度更快!有人吗?
【问题讨论】:
producten_new 中的 200 行 10 GET 变量 = 2K 查询!你需要重组!!! 索引? for 循环多久执行一次? 这有点复杂,也许是分开的东西。它正在放慢速度,因为您在 while 语句中有和 foreach 。几行可以正常工作,但如果数据增加,时间也会增加。 有点难以理解你在做什么,因为你的桌子似乎是荷兰语(猜猜!)但你可以做的第一件事是使用IN()
一次获取一堆物品和ORDER BY FIELD
当您发送第二个查询时(假设您在第二个查询中没有识别字段)
@JohnP:它是荷兰语,是的,他应该考虑使用英语作为通用语(变量、表、类和函数名称、cmets,...)。
【参考方案1】:
因为你是荷兰人(可以在你的编程中看到)我也会用荷兰语发布我的答案。
Ik heb 1 puntje al als snelheid 动词:omdat je $product_niet_aanwezig op true zet doet hij de rest van de foreach wel sneller maar hij doet het niet te min. Je kan ook een break statement erin zetten。 Dan "breakt" die uit de foreach 循环。
我有一点改进:因为您将 $product_niet_aanwezig 设置为 true,它将继续更快地执行 foreach 循环的其余部分,但它仍然会执行此操作。您还可以使用 break 语句“中断”出 foreach 循环。
【讨论】:
我现在正在使用break,谢谢!但并不是真正的性能调整。【参考方案2】:您应该首先考虑验证“where”条件中使用的所有键的索引。 (例如 producten_specs 表中的名称、值、product_id)
query12 只能调用一次:您的循环应该建立一个大条件,然后只发送 1 个查询。当您使用“count”时,您应该能够构建类似的东西
COUNT(id) FROM producten_specs WHERE [循环中的条件] GROUP BY product_id (虽然这可能并不完全准确)
我不知道您的 db shema,但尝试使用尽可能多的查询来构建视图。 使用您的 product_id 键进行连接并仅列出您需要的列的视图会更容易查询我的 2 美分 :)
【讨论】:
我已经编辑了我的开始帖子并添加了数据库信息。我希望它现在更清楚了。 我并不完全理解你的问题。虽然我可以建议使用小步骤: - 使用 query5 的结果继续运行您的 query12 - 尝试显示生成的 SQL 代码,并在数据库编辑器(phpmyadmin、mysql 工作台等)中运行选择查询.) 一旦你得到一个有效的查询,你可以尝试“升级”你生成它的方式。使用您的新代码,您的 query5 是否有效? Query5 工作正常。我不知道如何得到结果。例如,如何通过 query5 中的 product_id 和 $_GET 中的名称和值来选择 1 和 2(来自 product_specs 开始帖子中的示例,请参阅edit3)?【参考方案3】:您的代码
我看不出你的代码有什么问题,因为我是意大利人,我不明白该脚本背后的真正逻辑。尽管如此,在我看来,您正在运行一个循环,该循环将执行数千个查询,或者只执行一个(因为 if 条件),在这两种方式中,我建议使用 PDO 语句以某种方式缓存查询并生成他们第二次跑得更快。
PDO 发烧
由于第二个查询是在循环中执行的,我建议您使用PDO 来存储语句,并且每次执行语句时速度更快。
我在这里引用手册:
通过使用准备好的语句 应用程序避免重复 分析/编译/优化周期。这 意味着准备好的语句使用 资源更少,因此运行速度更快
我想让你注意到 PDO 也可以防止 SQL 注入:
[...] 开发人员可以确定不会发生 SQL 注入 [...]
索引
您必须在数据库端设置索引,以便查询特定表将花费更少的时间。 SQL 索引基本上类似于书籍索引,它们提供了一种快速定位信息的方法。
【讨论】:
感谢您的回复,但我的 PDO 没有过期。我会关注一些关于它的教程。我希望它能做我想做的事。 @Roy,PDO 是未来。我确实尝试过 mysql、mysqli 和 PDO,这是一场革命。相信我。 我已经阅读了一些教程并且 PDO 并不是那么困难,但是使用相同的查询 (query12) 脚本仍然很慢...?脚本必须完全改变。我不知道如何......我已经尝试过(请参阅我开始帖子中的edit2)。【参考方案4】:知道了!!感谢合作!
//Producten selecteren uit categorie en merk
$query5 = mysql_query("SELECT id FROM producten_new WHERE icecat_cat='".secure_in($obj->icecat)."'".$selecteren."");
while($row5 = mysql_fetch_assoc($query5))
$query5_ids .= $row5['id'].", ";
//Laatste , weg halen
$query5_ids = substr($query5_ids, 0, -2);
//Gets op een rijte zetten
foreach($_GET as $key=>$value)
if($key != "p" AND $key != "id" AND $key != "merk" AND $key != "submit" AND $value != "0")
$specs_gets .= $key.",".$value.";";
$aantal_gets++;
$uiteindelijk_selecteren .= "name='".secure_in(str_replace("_", " ", $key))."' AND value='".secure_in($value)."' OR ";
//Laatste ; weg halen
$specs_gets = substr($specs_gets, 0, -1);
//$uiteindelijk_selecteren = " AND ".substr($uiteindelijk_selecteren, 0, -4);
$uiteindelijk_selecteren = substr($uiteindelijk_selecteren, 0, -4);
//Overeenkomend met de get's selecteren
$query12 = mysql_query("SELECT product_id FROM producten_specs WHERE product_id IN (".secure_in($query5_ids).") AND ".$uiteindelijk_selecteren." ORDER BY product_id ASC");
while($row12 = mysql_fetch_assoc($query12))
if($product_onthouden == $row12['product_id'])
$product_onthouden_aantal++;
else
$product_onthouden_aantal = FALSE;
$product_onthouden = $row12['product_id'];
$product_onthouden_aantal = 1;
if($product_onthouden_aantal == $aantal_gets)
$query12_ids_ok .= $row12['product_id'].", ";
$aantal_producten++;
//Laatste , weg halen
$query12_ids_ok = substr($query12_ids_ok, 0, -2);
【讨论】:
很高兴它成功了!然后,您应该考虑“接受”为您带来最多输入的解决方案。 (随着时间的推移,接受度低的用户往往会收到更少的答案)以上是关于脚本太慢,mysql加入?的主要内容,如果未能解决你的问题,请参考以下文章