2015-05-26 123 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