我有這個表的MySQL索引用於特定查詢
attendance (4M rows at the moment, growing 1.2M per week):
-------------------------------------------------------------
| member_id | attendance_week | attendance_date | event_id |
------------------------------------------------------------
| INT (10) | TINYINT(2) | TIMESTAMP |TINYINT(3) |
-------------------------------------------------------------
attendance indeces:
--------------------------------------------------
| PRIMARY (attendance_week, member_id, event_id) |
| member_id (member_id) |
| event_id (event_id, attendance_week)
| total (attendance_week, event_id) |
--------------------------------------------------
members (400k rows at the moment growing 750 a week):
-------------------------
| member_id | dept_id |
-------------------------
| INT (10) |SMALLINT(5)|
-------------------------
member indeces:
-----------------------
| PRIMARY (member_id) |
|
-----------------------
活動是每週一次,這意味着你會看到對member_id
和event_id
每個星期。
現在我不得不產生一定部門報告每個事件,current attendance
(即,如果該成員已經簽入的),他們出席了至少4周(即attended
/total
事件的持續時間)
這是爲current_attendance
部分報告。我獲取所有成員,部門和LEFT JOIN
它本週的事件得到NULL
缺勤:
SELECT
m.member_id AS id,
a.event_id AS attended
FROM
members AS m
LEFT JOIN
attendance AS a
ON
a.member_id = m.member_id AND
a.attendance_week = :week AND
a.event_id = :event
WHERE
m.dept_id = :dept
GROUP BY
m.member_id
這是報告的attended
一部分。 :
SELECT
a.member_id,
COUNT(a.event_id)
FROM
attendance a
JOIN
members m
ON
a.member_id = m.member_id AND
m.dept_id = :dept
WHERE
a.attendance_week BETWEEN :start AND :end
GROUP BY
a.member_id
我大概可以簡單地LEFT JOIN
再次-ing第一查詢attendance
表合併這兩個查詢。
最後的total
部分
SELECT
attendance_week,
COUNT(DISTINCT event_id)
FROM
attendance
WHERE
attendance_week BETWEEN :start AND :end
GROUP BY
attendance_week
這些是將這些表上運行的主要查詢。在這一刻,查詢運行的平均值爲150 - 200ms(根據phpMyAdmin),我認爲這很慢。 EXPLAIN
告訴我,我的單位使用正在使用。
因此,這裏是我的問題:
- 有沒有辦法,我可以修改我的indeces和查詢,使這個更快的任何其他方式?
- 我假設MySQL有編譯語句的緩存。我不是在談論結果緩存,認爲PHP操作碼vs HTML緩存。我已經嘗試
SQL_NO_CACHE
,我仍然得到相同的響應時間,query_cache_size
是0.我可以發誓,我看到phpMyAdmin在800ms報告查詢一次(這是不可接受的),但我現在沒有得到它們。如何在每次運行時測量查詢的真實速度? - 如果我把這些查詢放在存儲過程中,這些會更快嗎?
- 存儲方法的任何想法?該數據庫目前大小約爲400MB。一年後,我不知道,也許3GB?這是可擴展的嗎?當談到DBA時,我真的很新,我讀過主從式複製和分區,但我不知道它是否適合這種情況。
如果您需要更多信息,請在下面評論。我會盡力提供它。我真的嘗試獨自做到這一點,但鑑於龐大的數據庫的要求(我的迄今爲止規模最大)和高性能,我真的需要一些建議:d
感謝
編輯
我剛剛意識到我的邏輯存在一個可怕的缺陷,新登記的成員將顯示出勤率低,因爲第三個查詢沒有考慮登記日期。我在我的成員表中有一個registration_date列,有什麼方法可以將該變量合併到查詢中嗎?或者將所有三個查詢合併一次?因爲它們都返回依賴於每個用戶的值。
編輯
我已經設法前兩個查詢合併:
SELECT
m.member_id AS id,
a.event_id AS attended,
COUNT(b.event_id) AS total_attended
FROM
members AS m
LEFT JOIN
attendance AS a
ON
a.member_id = m.member_id AND
a.attendance_week = :week AND
a.event_id = :event
LEFT JOIN
attendance AS b
ON
b.member_id = m.member_id AND
b.attendance_week BETWEEN :start AND :end
WHERE
m.dept_id = :dept
GROUP BY
m.member_id
此查詢925ms運行在後續請求第一次運行和15ms的。
這是結果上述查詢的EXPLAIN
members table:
id: 1
select_type: SIMPLE
table: m
type: ref
possible_keys: dept_id
key: dept_id
key_len: 3
ref: const
rows: 88
Extra: Using where; Using index
attendance table 1 (for the boolean attended part):
id: 1
select_type: SIMPLE
table: a
type: eq_ref
possible_keys: PRIMARY,member_id,event_id,total
key: PRIMARY
key_len: 6
ref: const,arms_db.m.member_id,const
rows: 1
Extra: Using index
attendance table 2 (for the total attendanded part):
id: 1
select_type: SIMPLE
table: b
type: ref
possible_keys: PRIMARY,member_id,total
key: member_id
key_len: 4
ref: arms_db.m.member_id
rows: 5
Extra: Using index
而且EXPLAIN
最後查詢:
id: 1
select_type: SIMPLE
table: attendance
type: range
possible_keys: PRIMARY,toral
key: total
key_len: 2
ref: NULL
rows: 9
Extra: Using where; Using index for groub-by
什麼是MySQL服務器版本? – 2012-08-10 01:53:24
5.5.25a社區服務器 – 2012-08-10 02:34:03
表是MyISAM還是InnoDB? – 2012-08-10 09:08:24