我有一個本土的(不是我自己的)版本具有以下數據結構系統:一個頁面我該如何改進這一個到許多ActiveRecord數據模型?
create_table "activities", :force => true do |t|
t.string "source"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.integer "head_revision_id"
end
add_index "activities", ["head_revision_id"], :name => "index_activities_on_head_revision_id"
add_index "activities", ["source"], :name => "index_activities_on_source"
create_table "activity_revisions", :force => true do |t|
t.integer "activity_id"
t.string "activity_type"
t.string "title"
t.text "content"
t.text "comment"
t.integer "modified_by_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "activity_revisions", ["activity_id"], :name => "index_activity_revisions_on_activity_id"
add_index "activity_revisions", ["activity_type"], :name => "index_activity_revisions_on_activity_type"
add_index "activity_revisions", ["title"], :name => "index_activity_revisions_on_title"
應用程序顯示的活動從最新到最舊,分頁(will_paginate)的列表20。這是用於生成列表中的查詢:
Activity.where(conditions)
.joins(:head_revision)
.includes(:head_revision)
.order('activities.id DESC')
的conditions
根據從搜索形式傳遞的值而變化。對於初始列表顯示,conditions
爲空。從表面上看,這個查詢很簡單,但在執行時,對於大型數據集來說,速度非常慢。我們目前有大約102,000條活動記錄和512,000條activity_revision記錄。在我們的生產服務器上,查詢需要將近2秒鐘才能提供計數。在開發環境中,這是糟糕的。
我覺得數據模型存在內在的錯誤,我希望有人能給我一個更好的方法。
編輯:解釋無條件的基本運行的查詢:
mysql> explain SELECT * FROM `activities` INNER JOIN `activity_revisions` ON `activity_revisions`.`id` = `activities`.`head_revision_id`;
+----+-------------+--------------------+--------+--------------------------------------+---------+---------+--------------------------------------------+--------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------------+--------+--------------------------------------+---------+---------+--------------------------------------------+--------+-------+
| 1 | SIMPLE | activities | ALL | index_activities_on_head_revision_id | NULL | NULL | NULL | 106590 | |
| 1 | SIMPLE | activity_revisions | eq_ref | PRIMARY | PRIMARY | 4 | cms_production.activities.head_revision_id | 1 | |
+----+-------------+--------------------+--------+--------------------------------------+---------+---------+--------------------------------------------+--------+-------+
2 rows in set (0.00 sec)
,並在COUNT(*)查詢:
mysql> explain SELECT count(*) FROM `activities` INNER JOIN `activity_revisions` ON `activity_revisions`.`id` = `activities`.`head_revision_id`;
+----+-------------+--------------------+--------+--------------------------------------+--------------------------------------+---------+--------------------------------------------+--------+------------- +
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------------+--------+--------------------------------------+--------------------------------------+---------+--------------------------------------------+--------+------------- +
| 1 | SIMPLE | activities | index | index_activities_on_head_revision_id | index_activities_on_head_revision_id | 5 | NULL | 106590 | Using index |
| 1 | SIMPLE | activity_revisions | eq_ref | PRIMARY | PRIMARY | 4 | cms_production.activities.head_revision_id | 1 | Using index |
+----+-------------+--------------------+--------+--------------------------------------+--------------------------------------+---------+--------------------------------------------+--------+------------- +
2 rows in set (0.00 sec)
更新:雖然我仍然覺得數據模型本身就不好,但我確定了現場和開發之間的大時序差異的原因是由於percona調整得不好。設置'innodb_buffer_pool_size = 7GB'可以大大提高查詢性能。 – Warren