2011-07-24 57 views
5

我正在一个数据库中存储一个对象,由大量的整数属性描述。真正的对象有点复杂,但现在让我们假设我将汽车存储在我的数据库中。每辆车都有很多整数属性来描述汽车(即最大速度,轴距,最大功率等),这些都可以由用户搜索。用户为每个对象定义了一个首选范围,并且由于有很多属性,所以很可能不会有任何车辆匹配所有的属性范围。因此,查询必须返回按最佳匹配排序的多辆汽车。选择哪个数据库来寻找最佳匹配记录?

SELECT *, SQRT(POW((a < min_a)*(min_a - a) + (a > max_a)*(a - max_a), 2) + 
       POW((b < min_b)*(min_b - b) + (b > max_b)*(b - max_b), 2) + 
       ...) AS match 
WHERE a < (min_a - max_allowable_deviation) AND a > (max_a + max_allowable_deviation) AND ... 
ORDER BY match ASC 

其中a和b是对象和min_a,max_a,min_b和max_b的属性是用户定义的值:

目前我使用下面的查询实现这在MySQL。基本上匹配是所需范围和属性的实际值之间的平方差的总和的平方根。值为0表示完美匹配。

该表包含几百万条记录,而WHERE clausule仅用于限制执行计算的记录数。索引放置在所有可查询记录上,查询需要500毫秒。我想改善这个数字,我正在研究如何改进这个查询。

此外,我想知道是否会有一个不同的数据库更适合执行这项工作。此外,我非常想更改为NoSQL数据库,因为它具有更灵活的数据方案选项。我一直在研究MongoDB,但无法找到有效(快速)解决此问题的方法。

有什么数据库比MySQL更适合这项工作吗?

+0

我失踪,你真正遇到了问题 - 这听起来像过早优化... –

+0

您可以查看SQL服务器或Oracle能够为视图编制索引。创建一个描述行及其匹配并为其编制索引的视图。 –

+0

@OMG:我认为他的意思是希望搜索类型:'SELECT macthCalculation FROM t WHERE(BETWEEN amin and amax)AND(b BETWEEN bmin and max)...',其中有几百万条记录并搜索超过2或更多的属性可能会缓慢与BTREE索引。 –

回答

4

看看R-trees。 (特定变体的页面会进入更多细节并显示伪代码)。这些数据结构允许您通过边界矩形进行查询,这是您按每个属性的范围搜索的问题。

将您的汽车视为n维空间中的点,其中n是描述您汽车的属性的数量。然后给出一个n个范围,每个描述一个属性,问题是找到包含在该n维超矩形中的所有点。 R-树有效地支持这个查询。 MySQL为其空间数据类型实现R树,但MySQL仅支持二维空间,这对您而言不够。我不知道任何常见的数据库数据库,它们支持现成的n维R-树,但是您可以对某些数据库提供对用户定义的树数据结构的良好支持,并且可以自己实现R树。例如,您可以使用子指针为MongoDB中的R-tree节点定义一个结构。然后,您将在您自己的代码中实施R-tree算法,同时让MongoDB负责存储数据。

此外,有这C++ header file实现R树,但目前它只是一个内存中的结构。虽然如果你的数据集只有几百万行,那么在启动时加载这个内存结构似乎是可行的,并且每当添加新车时(我认为这种情况很少发生),就更新它。

+0

+1支持n维数据的空间数据库将成为此类查询的理想解决方案。 @Ewout:同时检查Postgres:http://www.postgresql.org/docs/9.0/interactive/gist-intro.html –

+0

@奎唐:谢谢!我以前从来没有听说过R树,但它正在描述我的问题。可惜的是,不存在具有多维空间索引默认支持的数据库。 –

2

文本搜索引擎,如Lucene,很好地满足您的要求。他们允许您根据他们匹配的来“提升”匹配,例如,您可以将引擎大小定义为比轮底“更好匹配”。使用lucene非常简单,尤其是SUPER FAST。比mysql更快的方式。

Mysql提供了一个插件来提供基于文本的搜索,但我更喜欢单独使用它,这样它可以轻松扩展(只读,可以有多个lucene引擎),并且易于管理。

还检查出Solr,它位于lucene之上,允许您存储,检索和搜索简单的java对象(列表,数组等)。

+0

OP没有要求进行全文搜索。相反,他/她想要按范围查询不同的数字字段。 –

+0

用OP的话说:*有没有比MySQL更适合这项工作的数据库?* – Bohemian

+0

@Bohemian:谢谢你的回答!不过,我真的不知道像Lucene这样的文本搜索引擎如何帮助我。我的理解是Lucene不适合执行数值查询。我错过了Lucene的一些功能吗? –

1

可能,您的索引没有多大帮助,我想不出另一种数据库技术会更好。有几件事要用MySQL来试试....

我试着把一份数据拷贝到内存表中。至少表格扫描将存储在内存中...... http://dev.mysql.com/doc/refman/5.0/en/memory-storage-engine.html

如果这对您不利或帮助不大,您还可以尝试用户定义函数来优化匹配的计算。基本上,这意味着在C库您提供执行范围测试:

http://dev.mysql.com/doc/refman/5.0/en/adding-functions.html

+0

感谢您的回答!我已经考虑过内存表了。用户定义函数也是一个很好的建议。我会研究这些。 –

相关问题