我将对象存储在由许多整数属性描述的数据库中。真实的对象有点复杂,但现在让我们假设我在我的数据库中存储汽车。每辆车都有很多整数属性来描述汽车(即最大速度,轴距,最大功率等),这些属性可由用户搜索。用户为每个对象定义了一个首选范围,因为有很多属性,所以很可能不会有任何匹配所有属性范围的汽车。因此,查询必须返回按最佳匹配排序的多辆汽车。
目前我使用以下查询在MySQL中实现了这个:
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是用户定义的值。基本上,匹配是期望范围与属性的实际值之间的平方差之和的平方根。值为0表示完美匹配。
该表包含几百万条记录,并且仅引入WHERE clausule以限制执行计算的记录数。索引放在所有可查询记录上,查询大约需要500毫秒。我想改进这个数字,我正在研究改进这个查询的方法。
此外,我想知道是否会有更适合执行此工作的不同数据库。此外,由于其更灵活的数据方案选项,我非常希望更改为NoSQL数据库。我一直在研究MongoDB,但找不到有效(快速)解决这个问题的方法。
是否有比MySQL更适合这项工作的数据库?
答案 0 :(得分:4)
看看R-trees。 (特定变体的页面更详细,并提供伪代码)。这些数据结构允许您通过边界矩形进行查询,这是您按每个属性的范围搜索的问题。
将您的汽车视为n维空间中的点,其中n是描述您的汽车的属性数量。然后给出n个范围,每个范围描述一个属性,问题是找到该n维超矩形中包含的所有点。 R树有效地支持此查询。 MySQL为其空间数据类型实现R树,但MySQL仅支持二维空间,这对您来说是不够的。我不知道任何支持n维R树的常见数据库,但是您可以使用一些数据库,对用户定义的树数据结构有很好的支持,并自己实现R-tree最重要的是。例如,您可以使用子指针为MongoDB中的R树节点定义结构。然后,您将在自己的代码中实现R树算法,同时让MongoDB负责存储数据。
此外,还有这个C++ header file实现的R树,但目前它只是一个内存结构。虽然如果你的数据集只有几百万行,那么在启动时加载这个内存结构似乎是可行的,并且每当添加新车时都会更新它(我认为这种情况并不常见)。
答案 1 :(得分:2)
文本搜索引擎(例如Lucene)可以很好地满足您的要求。它们允许您根据匹配的 来“提升”命中率,例如,您可以将引擎大小定义为比轮距更“匹配”。使用lucene非常简单,最重要的是,它是超快。比mysql快。
Mysql提供了一个插件来提供基于文本的搜索,但我更喜欢单独使用它,这样它很容易扩展(只读,你可以有多个lucene引擎),并且易于管理。
同时查看Solr,它位于lucene之上,允许您存储,检索和搜索简单的java对象(列表,数组等)。
答案 2 :(得分: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