2011-09-26 68 views
0

我有一个汽车的分类列表网站,我正在开发使用PHP开发的过程。用户使用主页上的下拉选项框输入他们正在寻找的汽车的详细信息。当他们点击提交时,他们被带到结果页面,这是我遇到问题的地方。有关SQL查询速度和性能问题的帮助

它是建立在目前的方法是:

  1. 数据库中查询他们正在寻找汽车匹配任何结果。查询返回汽车的ID和广告的邮政编码;
  2. 然后检查每个广告的用户邮政编码和广告邮政编码之间的距离。这本身需要数据库查询来查找每个广告的单个邮政编码的坐标,并且对于有时可能超过350个结果的相当耗时;
  3. 然后使用if语句来确定距离是否小于或等于用户在主页上输入的距离
  4. 如果广告在允许的距离内,则它的ID被添加到数组;
  5. 然后计算该阵列中的广告总数,并用于确定取决于广告数量和要在页面上显示的广告数量的变量;
  6. 然后使用WHERE语句和数组中的ID执行广告表的第二个查询。例如SELECT * FROM adverts WHERE ID=1 AND ID=4 AND ID=23 ........查询中使用的ID的总数取决于第5点中提到的变量。然后,当用户单击下一页时,将从数组中剩下的位置重新运行查询然后查询被重新创建并执行。

我遇到的问题是,它需要很长时间才能完成,我正在寻找更多的资源和时间完成它的有意识的方式。

它最初被设计为用WHERE子句为每个用户对汽车的特定要求执行查询,然后在输出到页面之前使用if语句检查距离。这造成了页面编号的问题,因为无法确定与查询中返回的广告的距离要求相匹配的广告数量 - 因此,在完整广告被收集之前满足距离条件的情况下这样做计算要显示的确切数量的广告。

对不起,它有点长 - 希望它是有道理的。我没有包含任何代码,因为它会让它变得更长,而且它的逻辑问题与实际代码相反。

感谢您提出的任何建议。

有人要求表布局和SQL。开始.....

广告表

ID,品牌,型号,颜色,里程,发动机,年份,邮编

邮编表

ID,邮编,GridN,GridE,经度,纬度

用于首次查询以获得ID和邮政编码的SQL

SELECT ID, Postcode FROM adverts WHERE Make = '$subMake' AND Model = '$subModel'

SQL第二查询来获得使用符合距离要求,该ID的该广告的详细信息:

SELECT Make, Model, Year, Engine, Colour FROM adverts WHERE ID IN(1,2,6,90,112,898) 

(很抱歉,如果它不是语法正确的,它的工作,即SQL只是查询字符串的许多行的粗略轮廓)。

+5

'SELECT * FROM adverts WHERE ID = 1 AND ID = 4 AND ID = 23' would always always returns 0 rows?你的意思是'SELECT * FROM adverts WHERE ID IN(1,4,23)'instead? – GordonM

+1

某些答案最少需要的是表结构和您正在使用的SQL ... – Yahia

+2

是不是可以在您的SQL语句中执行距离计算,然后在返回之前进行筛选?这会快很多...... – Paddy

回答

0

最大的优化是查询邮政编码表并将网格引用存储在广告表中 - 当您插入广告行时。

这将大大减少对邮政编码表的访问次数。

您还可以通过在广告表上进行一些简单过滤来减少计算次数,如下所示。

从邮政编码表中获取用户GridN和GridE值。 计算minN为GridN - maxDistance,maxN为GridN + maxDistance,minE为GridE - maxDistance,maxE为GridE + Maxdistance。

然后,您可以在广告表中查询,像这样:

SELECT * FROM ADVERTS WHERE GridN between (minN,maxN) and GridE Between(minE,maxE); 

为了进一步加快这您可以添加索引GridN和GridE。

一旦您选择了行,您就可以计算“真实”距离并拒绝超出极限的几行。

+0

感谢这个答案,听起来像它正是我需要的 - 我将在今天晚些时候实施它。我难以理解的是,它究竟如何计算距离。我习惯用三角函数来计算它。这种方式如何工作?谢谢 – Max

+0

你并没有真正计算远程,你正在选择一个完全包含“圈子”的地理“方块”,该圈子定义了客户端的x英里。会有点向广场的角落落在圈外。 I.E.如果您的用户在10英里范围内选择了广告,则此查询仍然会选择位于您的客户以东9.9英里和东部9.9英里处的实际距离为14英里的添加 - 您需要进一步进行三角计算以拒绝这些离群值。但是,您已经通过简单比较有效地消除了99%的广告! –

+0

用于计算最小和最大距离的距离,除非我使用高于3000的数字,否则返回结果,然后随着距离的增加显示更多的距离。我是否必须改变距离测量单位的单位?除此之外,它已经加快了x10的整个过程。谢谢!! – Max

0

修改查询,使其包含邮政编码之间的距离,并限制为指定距离范围内的广告。

+0

Hi @mark这样做的问题是距离不在任何表中,因此无法查询。这个距离是根据每个用户在页面上计算出来的,并带有一个函数,该函数接受两个邮政编码(广告邮政编码和用户邮政编码),然后返回一个距离,然后检查该距离。 – Max

+0

Hi @Max。确定距离的函数可以作为用户定义的函数在数据库中创建吗? –

+0

这里的问题是你需要在每一行上做小学毕达哥拉斯计算“x平方和y平方和的平方根”。平方根的计算是什么吃的时间。 –

0

您应该将距离函数转换为具有所有可能的邮编组合的视图,然后您可以在查询中加入该距离函数而不是击中该函数,或者可以计算距离用户帖子50公里的纬度和经度代码

除此之外,如果您提供固定选项(这些网站大部分仅提供5,10,25,50,100作为距离选项),那么您可以预先计算这些距离计算并进一步去如果你真的想要做附加检查并将每个邮政编码映射到附近的所有邮政编码,那么你只需要为每个邮政编码计算5次(5个距离),并且可以从前一个值中排除结果,这样你从10km查询中排除5km,因为您有理寻找距离< = 10公里。

0

根据你的数据库,也许使用类似PostGIS的东西?

在Adverts表中为LonLat数据类型设置一个列,然后运行内置函数(如ST_DWithin)以便在距目标记录指定距离内找到所有具有LonLat的广告。

只是指出我发现使用静态邮编数据库的另一个问题是,它们很快就会过时(特别是对于新版本)。您可能还想使用Mapstraction之类的功能来返回来自Google/Yahoo等的地理编码结果,并保存该LonLat - 尽管您可能必须对邮政编码输入进行更多错误检查并将返回的结果限制为完全匹配。