之前,我问过this question about compound indexes on polymorphic foreign keys in ActiveRecord .我的问题的基础是我的理解,即索引应该基于您的列的基数,并且 Rails 的 STI 类型和多态 _type 列的基数通常很低。
承认我的问题的答案是正确的——索引高基数 _id 列和低基数 _type 列是有值(value)的,因为它们一起具有高基数——我的下一个问题是:你应该如何订购复合索引?
[owner_id, owner_type] 的索引将具有较高基数的字段放在第一位,而 [owner_type, owner_id] 将具有较高基数的字段放在第二位。使用前一个键的查询是否比使用后一个键的查询性能更高,还是它们的性能相同?
我问是因为这对我如何为 STI 模型服务的表排序复合键有特殊影响。 STI Rails 查找器几乎总是在类型列上进行查询——这又是一个通常基数较低的列。因此,类型列比其他索引更频繁地被查询。如果更频繁地查询类型列,那么使用类型领先索引可能是有意义的,因为不太具体的查询可以利用索引的第一部分来提高性能。但是,我不会以牺牲高度特定查询的性能为代价来获得更小的好处。利用索引的较高基数部分。
最佳答案
根据我自己的研究(但我不是专家 DBA),我了解到在决定复合键索引的顺序时需要考虑两件事。
首先,关于列的基数,索引通常更擅长搜索基数高的列。所以我倾向于将基数最高的列放在索引中的第一位。作为引用,有一篇标题为 MySQL Query Optimization 的文章上面写着:
Indexes work best for columns that have a high cardinality relative to the number of rows in the table (that is, columns that have many unique values and few duplicates).
在您的情况下,_id 列显然更符合该定义,因此它们更适合作为键的前缀。
要考虑的另一件事是这些索引的可重用性。大多数(如果不是全部)数据库系统允许重复使用复合键的前缀。例如,(owner_id, owner_type) 上的复合键也可用于 owner_id 上的查询,但不能用于 owner_type 上。
因此,根据您在问题中的解释,您最好使用两个索引:(owner_id, owner_type) 上的复合键索引和 (owner_type) 上的复合键索引>.
最后,一切都归结为您的数据集和查询。尝试多种场景,使用不同的复合键排序进行基准测试,看看什么是最佳解决方案。另外,不要忘记索引会对您的表造成写惩罚。
更新:还有另一个关于复合键索引的相当流行的 SO 问题:
关于mysql - MySQL 复合索引中键的高性能排序(WRT Rails 多态关联和 STI),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4947312/
文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co
我的Gallery模型中有以下查询:media_items.includes(:photo,:video).rank(:position_in_gallery)我的图库模型有_许多媒体项,每个都有一个照片或视频关联。到目前为止,一切正常。它返回所有media_items包括它们的photo或video关联,由media_item的position_in_gallery属性排序。但是我现在需要将此查询返回的照片限制为仅具有is_processing属性的照片,即nil。是否可以进行相同的查询,但条件是返回的照片等同于:.where(photo:'photo.is_processingIS
我看到其他人也遇到过类似的问题,但没有一个解决方案对我有用。0.3.14gem与其他gem文件一起存在。我已经完全按照此处指示完成了所有操作:https://github.com/brianmario/mysql2.我仍然得到以下信息。我不知道为什么安装程序指示它找不到include目录,因为我已经检查过它存在。thread.h文件存在,但不在ruby目录中。相反,它在这里:C:\RailsInstaller\DevKit\lib\perl5\5.8\msys\CORE\我正在运行Windows7并尝试在Aptana3中构建我的Rails项目。我的Ruby是1.9.3。$gemin
从一个返回表中所有值的模型中,我如何将其转换为名称值对的散列{column_value=>column_value}例如[{:id=>1,:name=>'first'},{:id=>2,:name=>'second'},{:id=>3,:name=>'third'}]到(指定:id和:name){'first'=>1,'second'=>2,'third'=>3} 最佳答案 你可以用inject在一行中完成:a=[{:id=>1,:name=>'first'},{:id=>2,:name=>'second'},{:id=>3,:na
我已经开始使用mysql2gem。我试图弄清楚一些基本的事情——其中之一是如何明确地执行事务(对于批处理操作,比如多个INSERT/UPDATE查询)。在旧的ruby-mysql中,这是我的方法:client=Mysql.real_connect(...)inserts=["INSERTINTO...","UPDATE..WHEREid=..",#etc]client.autocommit(false)inserts.eachdo|ins|beginclient.query(ins)rescue#handleerrorsorabortentirelyendendclient.commi
我正在使用带有单个“帐户”表的STI模型来保存用户和技术人员的信息(即用户...8)错误:test_the_truth(用户测试):ActiveRecord::StatementInvalid:PGError:ERROR:关系“技术人员”不存在:从“技术人员”中删除...从本质上讲,标准框架不承认Technicians和Users表(或PostgreSQL称它们为“关系”)不存在,事实上,应该别名为Accounts。有什么想法吗?我对RoR比较陌生,不知道如何解决这个问题而又不完全删除STI。 最佳答案 原来问题是由于存在:./te
我正在尝试绕过rails配置这个极其复杂的迷宫。到目前为止,我设法在ubuntu上设置了rvm(出于某种原因,ruby在ubuntu存储库中已经过时了)。我设法建立了一个Rails项目。我希望我的测试项目使用mysql而不是mysqlite。当我尝试“rakedb:migrate”时,出现错误:“!!!缺少mysql2gem。将其添加到您的Gemfile:gem'mysql2'”当我尝试“geminstallmysql”时,出现错误,告诉我需要为安装命令提供参数。但是,参数列表很大,我不知道该选择哪些。如何通过在ubuntu上运行的rvm和mysql获取rails3?谢谢。
我计划将STIinRails与以下模型一起使用:classPromoEvent和Discount在属性方面仅存在一些差异,因此我认为STI是一个不错的选择。我不确定如何确保,例如,仅Event具有额外的image_filename属性。我知道它会在promos表中,并且它必须是NULL-able以防我插入Discount行。如何确保Discount对象对image_filename属性一无所知(即未在Discount.column_names中列出>和/或无法设置它)Event知道它吗? 最佳答案 我认为这个概念是不同的,而你的Pr
在我的数据库中,我有一个表people,我正在使用单表继承,这些类:classPerson它生成的查询让我很困惑。我想要的是Member.all返回所有企业以及成员的任何其他子类型。它确实如此,但前提是我最近访问了商务舱。我认为这是因为我的类没有在开发模式下缓存(出于明显的原因),但它仍然看起来像奇怪的/错误的行为。这是Rails中的错误吗?或者它是否按预期工作?在任何一种情况下,任何人都可以想到一个用于开发目的的好的解决方案吗? 最佳答案 这是故意的行为——官方Rails指南AutoloadingandReloadingConst
在我的模型中,我像这样使用STI车辆型号:vehicle.rbclassVehicle汽车型号:car.rbclassCar总线模型:bus.rbclassBus如果我创建了一辆汽车,我能否以某种方式将其类型更改为车辆或巴士? 最佳答案 要永久更改类型,请更改type列的值。c1=Car.firstc1.name#BMWc1.update_attribute(:type,"Bus")b1=Bus.firstb1.name#BMW要同时更改内存中的对象类型而不从数据库中重新加载它,请使用“becomes,asin”c1=c1.beco