2015-05-26 126 views
0

我有查询,需要搜索3个表中的数据。Rails查询与包括需要很长的时间

公司表= 280K行

PostIndex表= 3.1k行

CompanyCategory = 5行

查询看起来是这样的:

query = '' 
associations = [:post_index, :company_category] 
Company.includes(associations).references(associations).where(query).order(:id).limit(25) 

为了简化问题,让我们坐在这个查询是空字符串。另外我有相关记录的索引。

这个查询加载时间= 1.2-1.3秒,即使是空的条件。并且最多2秒钟不空查询。

如何加快此查询?

事件这个简单的查询需要250ms的加载: Company.find_by(name: 'asd')

是否elasticsearch(或类似)是在我的情况下,唯一的解决办法?

PS我不能使用内部连接,因为并不是所有的企业都post_index

感谢您的帮助提前

更新1

只是意识到上面的查询需要约1.3秒指定的顺序和6毫秒没有指定的顺序。即使我按索引列(例如'companies.id')排序,它仍然很慢,需要1.3秒。有什么建议么?

更新2

我试着做了解释疑问,这里是结果:

Explain queryhttp://i.stack.imgur.com/VzKE6.png

我检查的模式,我有分类与PostIndices指标有:

add_index "companies", ["company_category_id"], name: "index_companies_on_company_category_id", using: :btree 
add_index "companies", ["post_index_id"], name: "index_companies_on_post_index_id", using: :btree 

indexeshttp://i.stack.imgur.com/eInwr.png

对于这两个模型,与公司模型的关系完全相同。但相应的解释,它表现不同。我不熟悉EXPLAIN,但从我读过的内容 - 加入类别时,加入类型是ALL,这是不好的。它搜索138632 * 5行。

但是,当加入PostIndex时,加入类型是eq_ref,所以它搜索138632 * 1行。所以我完全困惑为什么会发生这种情况。任何想法?

UPDATE 4

SHOW CREATE TABLE公司;

enter image description herehttp://i.stack.imgur.com/E6CEO.png

UPDATE 5

SLOW RUBY:

Company.includes(associations).references(associations).where(query).order(:id).limit(25).explain

SLOW SQL:

SELECT `companies`.`id` AS t0_r0, `companies`.`name` AS t0_r1, 
     `companies`.`address` AS t0_r2, `companies`.`post_index_id` AS t0_r3, 
     `companies`.`tel` AS t0_r4, `companies`.`mobile` AS t0_r5, 
     `companies`.`fax` AS t0_r6, `companies`.`email` AS t0_r7, 
     `companies`.`website` AS t0_r8, `companies`.`vat` AS t0_r9, 
     `companies`.`company_category_id` AS t0_r10, `companies`.`nace` AS t0_r11, 
     `companies`.`union` AS t0_r12, `companies`.`note` AS t0_r13, 
     `companies`.`created_at` AS t0_r14, `companies`.`updated_at` AS t0_r15, 
     `companies`.`ean` AS t0_r16, `companies`.`deleted_at` AS t0_r17, 
     `companies`.`sector` AS t0_r18, `companies`.`status` AS t0_r19, 
     `post_indices`.`id` AS t1_r0, `post_indices`.`county` AS t1_r1, 
     `post_indices`.`postal_code` AS t1_r2, `post_indices`.`group_part` AS t1_r3, 
     `post_indices`.`group_number` AS t1_r4, `post_indices`.`group_name` AS t1_r5, 
     `post_indices`.`city` AS t1_r6, `post_indices`.`created_at` AS t1_r7, 
     `post_indices`.`updated_at` AS t1_r8, 
     -- EXTRA: 
     `company_categories`.`id` AS t2_r0, 
     `company_categories`.`name` AS t2_r1, `company_categories`.`created_at` AS t2_r2, 
     `company_categories`.`updated_at` AS t2_r3 
     -- END EXTRA 
    FROM `companies` 
    LEFT OUTER JOIN `post_indices` ON `post_indices`.`id` = `companies`.`post_index_id` 
     -- EXTRA: 
    LEFT OUTER JOIN `company_categories` ON `company_categories`.`id` = `companies`.`company_category_id` 
     -- END EXTRA 
    WHERE `companies`.`deleted_at` IS NULL 
    ORDER BY `companies`.`id` ASC 
    LIMIT 25 

FAST RUBY:

Company.includes(associations.first).references(associations.first).where(query).order(:id).limit(25).explain

FAST SQL:

SELECT `companies`.`id` AS t0_r0, `companies`.`name` AS t0_r1, 
     `companies`.`address` AS t0_r2, `companies`.`post_index_id` AS t0_r3, 
     `companies`.`tel` AS t0_r4, `companies`.`mobile` AS t0_r5, 
     `companies`.`fax` AS t0_r6, `companies`.`email` AS t0_r7, 
     `companies`.`website` AS t0_r8, `companies`.`vat` AS t0_r9, 
     `companies`.`company_category_id` AS t0_r10, `companies`.`nace` AS t0_r11, 
     `companies`.`union` AS t0_r12, `companies`.`note` AS t0_r13, 
     `companies`.`created_at` AS t0_r14, `companies`.`updated_at` AS t0_r15, 
     `companies`.`ean` AS t0_r16, `companies`.`deleted_at` AS t0_r17, 
     `companies`.`sector` AS t0_r18, `companies`.`status` AS t0_r19, 
     `post_indices`.`id` AS t1_r0, `post_indices`.`county` AS t1_r1, 
     `post_indices`.`postal_code` AS t1_r2, `post_indices`.`group_part` AS t1_r3, 
     `post_indices`.`group_number` AS t1_r4, `post_indices`.`group_name` AS t1_r5, 
     `post_indices`.`city` AS t1_r6, `post_indices`.`created_at` AS t1_r7, 
     `post_indices`.`updated_at` AS t1_r8 
    FROM `companies` 
    LEFT OUTER JOIN `post_indices` ON `post_indices`.`id` = `companies`.`post_index_id` 
    WHERE `companies`.`deleted_at` IS NULL 
    ORDER BY `companies`.`id` ASC 
    LIMIT 25 

更多细节在此要旨:

https://gist.github.com/vlad-ninja/1d6c77eeb0a328341640

enter image description herehttp://i.stack.imgur.com/NhpaX.png

UPDATE 6

enter image description here

UPDATE 7

解释格式JSON要旨:

https://gist.github.com/vlad-ninja/b4a962aabe1a34ad773a

+0

大概每个表都有一个索引的Id列。但是他们有一个外键列到索引的其他表吗?例如,'company.category_id'有一个索引?这应该使联接更快。 – Turophile

+0

是的,我编入了'company.categrory_id'和其他foreign_keys。但我认为原因是因为加入类别。因为当我只加入PostIndex时,一切都很顺利和快速。请参阅更新2 – vladra

回答

0

对于companies,具有INDEX(deleted_at, id)

请提供SHOW CREATE TABLE companies;有一些细节我们需要看到。

+0

认为没有人会回答这个问题。请检查更新4查询的详细信息 – vladra

+0

确定。现在的表现如何? EXPLAIN有改变吗? –

+0

不幸的是没有。 1.5毫秒没有分类和2500毫秒分类。 https://www.dropbox.com/s/p2r93xavsk6aeff/Screenshot%202015-06-09%2016.53.42.png?dl=0 – vladra