1

我正在建立一个有很多过滤器的网站。每次单击/缩小搜索范围时,都会为所有过滤器重新计算所有计数器。我意识到我在这里造成了一些问题,因为每次点击时,我都会通过大约 50 个计数查询来重新计算所有过滤器。当有许多用户同时使用该站点时,这将产生相当大的数据库负载..

如果您需要更多上下文,过滤器计数器看起来像这样:http: //screencast.com/t/3bxrWTAtm

优化这些计数的最佳方法是什么?我可以使用 memcache,但由于可能会出现新的列表,因此最多必须缓存大约 15-30 分钟。

以下是 COUNT 查询之一的示例:

SELECT COUNT(id) AS numOfRows FROM (SELECT `id`, `theLatitude`, `theLongitude`, ( 3959 * acos( cos( radians(45.5086699) ) * cos( radians( theLatitude ) ) * cos( radians( theLongitude ) - radians(-73.5539925) ) + sin( radians(45.5086699) ) * sin( radians( theLatitude ) ) ) ) AS distance  FROM `housing` WHERE  (`elevator` = '1') AND ( `property-type` = 'loft' )  HAVING distance < 75) AS `newid`

住房表如下所示:

CREATE TABLE IF NOT EXISTS `housing` (
`id` varchar(10) NOT NULL,
`date` datetime NOT NULL,
`user` varchar(20) NOT NULL,
`email` varchar(50) NOT NULL,
`title` varchar(60) NOT NULL,
`address` varchar(120) DEFAULT NULL,
`formatted_address` varchar(120) NOT NULL,
`theLatitude` double DEFAULT NULL,
`theLongitude` double DEFAULT NULL,
`property-type` varchar(20) NOT NULL,
`square-feet` int(9) DEFAULT NULL,
`bathrooms` double NOT NULL DEFAULT '0',
`bedrooms` int(2) NOT NULL DEFAULT '0',
`price` int(10) DEFAULT NULL,
`priceUSD` int(10) NOT NULL,
`currency` varchar(3) DEFAULT NULL,
`period` varchar(5) DEFAULT NULL,
`lease-terms` varchar(20) NOT NULL,
`available-from` date NOT NULL,
`contactName` varchar(30) NOT NULL,
`contactPhone1` varchar(30) NOT NULL,
`contactPhone2` varchar(30) NOT NULL,
`description` text NOT NULL,
`cats` tinyint(1) NOT NULL DEFAULT '0',
`small-dogs` tinyint(1) NOT NULL DEFAULT '0',
`small-pets` tinyint(1) NOT NULL DEFAULT '0',
`big-dogs` tinyint(1) NOT NULL DEFAULT '0',
`alarm-system` tinyint(1) NOT NULL DEFAULT '0',
`air-conditioning` tinyint(1) NOT NULL DEFAULT '0',
`balcony` tinyint(1) NOT NULL DEFAULT '0',
`carpet-floors` tinyint(1) NOT NULL DEFAULT '0',
`dishwasher` tinyint(1) NOT NULL DEFAULT '0',
`electricity` tinyint(1) NOT NULL DEFAULT '0',
`fireplace` tinyint(1) NOT NULL DEFAULT '0',
`furniture` tinyint(1) NOT NULL DEFAULT '0',
`heating` tinyint(1) NOT NULL DEFAULT '0',
`high-ceilings` tinyint(1) NOT NULL DEFAULT '0',
`hot-water` tinyint(1) NOT NULL DEFAULT '0',
`natural-gas` tinyint(1) NOT NULL DEFAULT '0',
`spa-hot-tub` tinyint(1) NOT NULL DEFAULT '0',
`refrigerator` tinyint(1) NOT NULL DEFAULT '0',
`stove` tinyint(1) NOT NULL DEFAULT '0',
`storage-space` tinyint(1) NOT NULL DEFAULT '0',
`walk-in-closets` tinyint(1) NOT NULL DEFAULT '0',
`washer-dryer` tinyint(1) NOT NULL DEFAULT '0',
`doorman` tinyint(1) NOT NULL DEFAULT '0',
`elevator` tinyint(1) NOT NULL DEFAULT '0',
`health-facilities` tinyint(1) NOT NULL DEFAULT '0',
`inside-parking` tinyint(1) NOT NULL DEFAULT '0',
`laundry-facilities` tinyint(1) NOT NULL DEFAULT '0',
`outside-parking` tinyint(1) NOT NULL DEFAULT '0',
`pool-sauna` tinyint(1) NOT NULL DEFAULT '0',
`wheelchair-access` tinyint(1) NOT NULL DEFAULT '0',
`authnumber` varchar(15) NOT NULL,
`validated` tinyint(1) NOT NULL DEFAULT '0',

主键 ( id) ) 引擎=MyISAM 默认字符集=latin1;

用户可以过滤 50 多个字段。

任何能指出我正确方向的东西都将不胜感激。

4

3 回答 3

0

我过去曾为一个网站做过类似的事情,包括类别和产品。我的方法是首先为每组过滤器编写一个应用程序调用。换句话说,以获取您的功能列表为例。

接下来,您绝对希望将该调用缓存在您的应用程序/Web 代码中。您可以缓存来自您的应用程序或为您的应用程序提供支持的服务的函数调用。例如,如果您有一个函数“getListingFeatures()”,您将在 Memcached 中将该函数缓存 2 分钟。当它过期时,它当然会去数据库并再次将其加载到缓存中。

您绝对可以将到期时间设置为较低的值。

还可以考虑让您的到期时间相当随机,以避免“Thundering Herds”(http://en.wikipedia.org/wiki/Thundering_herd_problem)。

我强烈建议您继续使用它并使用 Memcached。

于 2013-01-14T03:23:07.320 回答
0

首先,Explain在您的查询中使用并查看您的 mysql 必须检查多少行。尝试了解幕后发生的事情。

其次,如果可能的话,使用Join而不是嵌套查询。这在mysql上要轻得多。

第三,在您的过滤器列上试验不同的索引。

编辑:Bill Karwin 教我 1,2,3 索引规则。即,WHEREORDER BYSELECT。WHERE 语句中的列通常也是最重要的添加索引。

现在,对于使用此类密集计算的查询,我不能说哪种索引最适合您,这就是您应该做一些试验的原因。

观看此幻灯片以了解索引的基础知识。所有功劳归功于比尔·卡尔文。

于 2013-01-14T04:07:56.447 回答
0
  1. Explain按照 hellohellosharp 的回答中的建议使用。
  2. 尝试添加index到表中的属性。
  3. 使用 Mysql 缓存。
  4. 使用内存缓存。强烈建议!
于 2013-01-14T04:20:01.063 回答