帮助解决SQL查询速度和性能问题


Help with a SQL querying speed and performance issue

我有一个汽车分类上市网站,我正在开发内置PHP的过程中。用户使用主页上的下拉选项框输入他们正在寻找的汽车的详细信息。当他们点击提交时,他们被带到结果页面,这就是我遇到问题的地方。

目前的设置方式是:

  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,邮政编码,栅格,栅格,经度,纬度

第一次查询获取ID和邮政编码的SQL

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

第二个查询使用与距离要求匹配的ID获取广告详细信息的SQL:

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

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

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

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

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

从邮政编码表中获取Users 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中添加索引。

一旦选择了行,就可以计算"实际"距离,并拒绝超出限制的少数行。

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

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

进一步,如果你提供固定的选项(大多数这些网站提供5,10,25,50,100作为距离选项),那么你可以预先计算这些距离计算,甚至更进一步,你可以做额外的检查,并将每个邮政编码映射到附近的所有邮政编码,如果你真的想要,你只需要计算它5次(5个距离)为每个邮政编码,你可以从以前的值中排除结果,这样您就从10km查询中排除了5km,因为您只查找距离<= 10km。

根据您的数据库可能使用PostGIS之类的东西?

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

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