也许解决方案很明显,但我似乎找不到合适的解决方案。
在我接下来的项目中,会有一个主表,它的数据会被频繁读取。更新/插入/删除速度不是问题。
该主表中的项目与 4 个或更多类别相关联。一个项目可以有 50 - 100 或更多的关系在一个类别中。
将对数据库执行的最常见操作:
我对如何为上述内容创建数据库的第一个想法是这样的(我猜是经典方法):
首先,我为四个类别中的每一个创建一个 category 表:
id - PK, int(11), index
name - varchar(100)
然后我将有一个item表:
id - PK, int(11), index
... some more data fields, about 30 or so ...
为了关联类别表,将有 4 个或更多查找/MM 表,如下所示:
id_item - int(11)
id_category - int(11)
查询看起来像这样:
select
item.*
from
item
inner mm_1 on mm_1.id_item = item.id
inner join cat_1 on cat_1.id = mm_1.id_category and cat_1.id in (1, 2, ... , 100)
inner mm_2 on mm_2.id_item = item.id
inner join cat_2 on cat_2.id = mm_2.id_category and cat_2.id in (50, 51, ... , 90)
当然,上述方法对 MM 表有效,但由于应用程序应提供非常好的 SELECT 性能,我使用真实世界的数据量(item 中的 100.000 条记录)对其进行了测试 表,每个类别中有 50 - 80 个关系),但它没有我预期的那么快,即使有索引也是如此。我还尝试在选择时使用 WHERE EXISTS 而不是 INNER JOIN。
我的第二个想法是只使用上面的 item 表对数据进行反规范化。
看完this blog post关于使用位掩码,我试了一下并为每个类别分配了一个位值:
category 1.1 - 1
category 1.2 - 2
category 1.3 - 4
category 1.4 - 8
... etc ...
因此,如果一个 item 被标记为 category 1.1 和 category 1.3,它的位掩码为 5,然后我将其存储在字段 item.bitmask 中,我可以像这样查询它:
select count(*) from item where item.bitmask & 5 = 5
但是性能也不是很好。
这种位掩码方法的问题:当涉及位运算符时,mysql 不使用任何索引,即使 item.bitmask 的类型为 BIGINT 我也只能处理最多 64 个关系,但我需要支持最多 100 个每个类别。
就是这样。除了可能用许多字段污染 item 表之外,我想不出更多的东西,例如 category_1_1 到 category_4_100 每个包含 1 或0. 但这可能会导致 select 的 WHERE 子句中出现许多 AND,这似乎也不是一个好主意。
那么,我有哪些选择?还有更好的想法吗?
编辑:作为对 Cory Petosky 评论““一个项目在一个类别中可以有 50 - 100 或更多关系”是什么意思。”的回应?是什么意思?
为了使它更具体,item 表表示一个图像。图像是按情绪分类的其他标准之一(情绪将是 4 个类别之一)。所以它看起来像这样:
Image:
- Category "mood":
- bright
- happy
- funny
- ... 50 or so more ...
- Category "XYZ":
- ... 70 or so more ...
如果我的图像表是 C# 中的一个类,它将如下所示:
public class Image {
public List<Mood> Moods; // can contain 0 - 100 items
public List<Some> SomeCategory; // can contain 0 - 100 items
// ...
}
最佳答案
这个呢(伪代码):
Item (image)
Id PK, int(11)
Name varchar(100)
Category (mood, xyz)
Id PK, int(11)
Name varchar(100)
Relations (happy, funny)
Id PK, int(11)
Name varchar(100)
ItemCategories
Id PK, int(11)
ItemId FK, int(11)
CategoryId FK, int(11)
ItemCategoryRelations
ItemCategoriesId FK, int(11)
RelationId FK, int(11)
SELECT *
FROM Item
JOIN ItemCategories ON Item.Id = ItemCategories.ItemId
WHERE ItemCategories.CategoryId IN (1, 2, ..., 10)
以下版本少用一张表,但不支持没有关系的类别,关系不能复用。因此,如果符合您的数据结构要求,它才有效:
Item (image)
Id PK, int(11)
Name varchar(100)
Category (mood, xyz)
Id PK, int(11)
Name varchar(100)
Relations (happy, funny)
Id PK, int(11)
CategoryId FK, int(11)
Name varchar(100)
ItemRelations
ItemId FK, int(11)
RelationId FK, int(11)
SELECT *
FROM Item
JOIN ItemRelations ON Item.Id = ItemRelations.ItemId
JOIN Relations ON Relations.Id = ItemRelations.RelationsId
WHERE Relations.CategoryId IN (1, 2, ..., 10)
关于mysql - 存储标有多个类别的项目 - 位掩码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1845513/
Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题
我有多个ActiveRecord子类Item的实例数组,我需要根据最早的事件循环打印。在这种情况下,我需要打印付款和维护日期,如下所示:ItemAmaintenancerequiredin5daysItemBpaymentrequiredin6daysItemApaymentrequiredin7daysItemBmaintenancerequiredin8days我目前有两个查询,用于查找maintenance和payment项目(非排他性查询),并输出如下内容:paymentrequiredin...maintenancerequiredin...有什么方法可以改善上述(丑陋的)代
如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何
我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2
我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘
我已经像这样安装了一个新的Rails项目:$railsnewsite它执行并到达:bundleinstall但是当它似乎尝试安装依赖项时我得到了这个错误Gem::Ext::BuildError:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcheckingforlibkern/OSAtomic.h...yescreatingMakefilemake"DESTDIR="cleanmake"DESTDIR="
我正在尝试修改当前依赖于定义为activeresource的gem:s.add_dependency"activeresource","~>3.0"为了让gem与Rails4一起工作,我需要扩展依赖关系以与activeresource的版本3或4一起工作。我不想简单地添加以下内容,因为它可能会在以后引起问题:s.add_dependency"activeresource",">=3.0"有没有办法指定可接受版本的列表?~>3.0还是~>4.0? 最佳答案 根据thedocumentation,如果你想要3到4之间的所有版本,你可以这
假设我有这个范围:("aaaaa".."zzzzz")如何在不事先/每次生成整个项目的情况下从范围中获取第N个项目? 最佳答案 一种快速简便的方法:("aaaaa".."zzzzz").first(42).last#==>"aaabp"如果出于某种原因你不得不一遍又一遍地这样做,或者如果你需要避免为前N个元素构建中间数组,你可以这样写:moduleEnumerabledefskip(n)returnto_enum:skip,nunlessblock_given?each_with_indexdo|item,index|yieldit