[英]How can I speed up a count(*) which is already using indexes? (MyISAM)
我有3個大表(10k,10k和100M行),並且試圖對它們的連接進行簡單的計數,其中所有連接的列都已建立索引。 為什么COUNT(*)需要這么長時間,並且我如何加快它(沒有觸發器和運行摘要)?
mysql> describe SELECT COUNT(*) FROM `metaward_alias` INNER JOIN `metaward_achiever` ON (`metaward_alias`.`id` = `metaward_achiever`.`alias_id`) INNER JOIN `metaward_award` ON (`metaward_achiever`.`award_id` = `metaward_award`.`id`) WHERE `metaward_award`.`owner_id` = 8;
+----+-------------+-------------------+--------+-------------------------------------------------------+----------------------------+---------+---------------------------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------------------+--------+-------------------------------------------------------+----------------------------+---------+---------------------------------+------+-------------+
| 1 | SIMPLE | metaward_award | ref | PRIMARY,metaward_award_owner_id | metaward_award_owner_id | 4 | const | 1552 | |
| 1 | SIMPLE | metaward_achiever | ref | metaward_achiever_award_id,metaward_achiever_alias_id | metaward_achiever_award_id | 4 | paul.metaward_award.id | 2498 | |
| 1 | SIMPLE | metaward_alias | eq_ref | PRIMARY | PRIMARY | 4 | paul.metaward_achiever.alias_id | 1 | Using index |
+----+-------------+-------------------+--------+-------------------------------------------------------+----------------------------+---------+---------------------------------+------+-------------+
3 rows in set (0.00 sec)
但是實際上運行查詢大約需要10分鍾,而我正在使用MyISAM,因此在此期間表已完全鎖定
我猜想原因是您對三個表進行了巨大的聯接(如果不先應用where子句,結果將是10k * 10k * 100M = 10 16行)。 嘗試重新排序聯接(例如,以metaward_award
,然后僅metaward_achiever
了解所需的時間,然后嘗試插入metaward_alias
,可能使用子查詢來強制執行您的首選評估順序)。
如果這樣做沒有幫助,您可能必須對數據進行非規范化,例如,通過存儲特定metaward_achiever
的別名數量。 然后,您將完全擺脫一個聯接。 也許您甚至可以緩存metaward_award
的總和,具體取決於您的數據更新的頻率和頻率。
可能有幫助的另一件事是將所有數據庫內容都放入RAM :-)
確保您具有以下指標:
metaward_alias id
metaward_achiever alias_id
metaward_achiever award_id
metaward_award id
metaward_award owner_id
我敢肯定,很多人也會建議指望特定的列,但是在MySql中,這對您的查詢沒有任何影響。
更新 :
您也可以嘗試在主表而不是已連接表之一上設置條件。 那會給你同樣的結果,但是可能更快(我不知道MySql有多聰明):
SELECT COUNT(*) FROM `metaward_award`
INNER JOIN `metaward_achiever`
ON (`metaward_achiever`.`award_id` = `metaward_award`.`id`)
INNER JOIN `metaward_alias`
ON (`metaward_alias`.`id` = `metaward_achiever`.`alias_id`)
WHERE `metaward_award`.`owner_id` = 8
10分鍾對於該查詢來說太長了。 我認為您必須擁有非常小的密鑰緩存。 您可以通過以下方式獲取其大小(以字節為單位):
SELECT @@key_buffer_size
首先,您應該運行ANALYZE TABLE或OPTIMIZE TABLE 。 他們將對您的索引進行排序,並可以稍微改善性能。
您還應該查看是否可以對列使用更緊湊的類型。 例如,如果您的所有者,獎勵或別名不超過1600萬,則可以將INT列更改為MEDIUMINT(當然是UNSIGNED)。 在某些情況下甚至可能是SMALLINT? 這樣可以減少索引占用量,並將更多的索引放入緩存中。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.