如何设计Redis数据结构以便在redis中执行类似于DB查询的查询?

时间:2016-05-16 09:49:01

标签: sql redis

我有像Job,JobInfo这样的表格。我想执行如下的查询 -

“SELECT J.JobID FROM Job J,JobInfo B WHERE B.JobID = J.JobID AND BatchID = 5850 AND B.Status = 0 AND J.JobType<> 2”

如何编写我的redis数据类型,以便我可以用redis映射这些查询?

如果我尝试在redis哈希中映射表作业的行,例如(hash j jobid 1 status 2)&类似地,表JobInfo的行再次成为redis哈希(hash jinfo jobid 1 jobtype 3。)

所以我的表可以是一组哈希。可以使用条目JobSet设置作业表:jobid&可以使用JobInfoSet:jobid

等条目设置JobInfo表

但是当我在JobSet& amp; JobInfoSet。我将如何查询该哈希以获取密钥?由于set jobSet的哈希内容与表JobInfoSet的哈希内容不同(它们可能具有不同的键值对。

那么我将作为SINTER的输出得到什么?我将如何将该输出作为键值对查询?

因此表格将是redis哈希的集合

3 个答案:

答案 0 :(得分:2)

Redis不是用于以SQL方式构造数据的。除了内存中的键值存储,它还支持五种类型的数据结构:字符串,散列,列表,集合和排序集。在高级别,这是一个充分的暗示,Redis旨在解决由于关系数据模型中的高计算而出现的性能问题。但是,如果要在内存结构中执行sql查询,可能需要查看memsql

答案 1 :(得分:1)

让我们将SQL语句分解为不同的组件,我将尝试展示redis如何完成各个部分。

从Job J中选择J.JobID,J.JobName;

我们使用SQL主索引作为redis中的redis自然索引,将“Job”中的每一行转换为redis中的哈希值。 例如: SQL

==JobId==|==Name==
123        Fred

Redis的 HSET职位:123姓弗雷德 可以概念化为

Job-123 => {"Name":"Fred"}

因此,我们可以将列存储为redis

中的哈希字段

假设我们为JobInfo做同样的事情。每个JobInfo对象都有自己的ID

JobInfo-876 => {"meta1": "some value", "meta2": "bla", "JobID": "123"}

在sql中,我们通常会在JobInfo.JobID上创建一个二级索引,但在NoSql中我们维护自己的二级索引。

排序集很适合这个。 因此,当我们想通过某个字段获取JobInfo对象时,在这种情况下JobId可以将它添加到这样的有序集合中 ZADD JobInfo-JobID 123 JobInfo-876

这会产生一个包含1个元素的{JobInfo-876},其得分为123.我意识到强制所有JobID进入得分的浮动范围是一个坏主意,但在这里与我合作。 / p>

现在,当我们想要找到给定JobID的所有JobInfo对象时,我们只需对索引进行日志(N)查找。 ZRANGEBYSCORE JobInfo-JobID 123 123 返回“JobInfo-876”

现在,要实现简单连接,我们只需通过JobID存储Job键来重用此JobInfo-JobID索引。 ZADD JobInfo-JobID 123 Job-123

因此在做类似的事情时 SELECT J.JobID,J.Name,B.meta1 FROM Job,JobInfo USING(JobID)。

这将转换为扫描JobInfo-JobID二级索引并重新组织返回的Job和JobInfo对象。 ZRANGEBYSCORE JobInfo-JobID -inf + inf WITHSCORES 5 - > (Job-123,JobInfo-876)

这些对象都共享相同的JobID。 CLient方面,然后您将异步获取所需的字段。或者您可以将这些查找嵌入到lua脚本中。这个lua脚本可以让redis挂起很长时间。通常redis试图对客户公平,并且更喜欢您使用短批量查询而不是一个长查询。

现在我们遇到了一个大问题,如果我们想要结合二级索引怎么办?假设我们在JobInfo.Status上有一个二级索引,在Job.JobType上有另一个索引。 如果我们使用正确的JobType创建一组所有作业并将其用作JobInfo-JobID共享辅助索引的过滤器,那么我们不仅消除了错误的Job元素,还消除了每个JobInfo元素。我们可以,我想在交叉点上获取分数(JobID)并使用这些分数重新获取所有JobInfo对象,但是我们失去了一些我们做过的过滤。

正是在这一点上,redis崩溃了。

这是一篇关于redis自己创建者的二级索引的文章:http://redis.io/topics/indexes 他为了过滤目的而触及多维索引。如您所见,他以非常通用的方式设计数据结构。最吸引人的是具有相同分数的有序集元素以字典顺序存储的事实。因此,您可以轻松地将所有元素的得分分别设置为0并依赖Redis的速度,并使用它更像cockroachDB,它依赖于全局顺序来实现许多SQL功能。

答案 2 :(得分:1)

另一个答案对于redis版本3.4

是完全正确的

最新版本的redis,从4.0开始,包括对模块的支持。

模块极其强大,我只是写了一个小模块将SQLite嵌入到redis本身; rediSQL

使用该模块,您实际上可以在redis实例中使用功能齐全的SQL数据库。