2016-08-09 63 views
0

我正在使用MySQL與innodb在Rails中的應用程序。我需要經常抓取整個表的數量,我知道使用innodb,計算表中的所有記錄可能會非常昂貴,因爲它需要全表掃描。我正在查看軌道控制檯中的典型表格,並查看計數記錄的查詢時間。到目前爲止,我發現第一次計算記錄需要很長時間,但在後續的嘗試中速度要快得多。例如:在mysql innodb表中計數記錄

2.2.2 :002 > Request.count 
    (683.7ms) SELECT COUNT(*) FROM `requests` 
=> 260588 
2.2.2 :003 > Request.count 
    (47.6ms) SELECT COUNT(*) FROM `requests` 
=> 260588 
2.2.2 :004 > Request.count 
    (46.7ms) SELECT COUNT(*) FROM `requests` 
=> 260588 

因此,首先,我是否需要擔心優化此結果?計數可能被Rails或mySql或InnoDB緩存,沒有什麼可擔心的。

我打算假設在任何給定時間多個用戶正在寫入表的生產環境中仍然有些問題需要擔心。在那種情況下,我如何「重置」高速緩存或是什麼讓我對計數時間有一種虛幻的陽光看法,以便我可以做一些誠實的基準測試?我嘗試寫入記錄,或者只是用reload!重新載入控制檯,但我從來沒有得到最初的時間。我敢打賭,如果我退出控制檯並重新啓動將執行此操作的mysql,但我寧願不必努力工作。

最後,我聽說類似下面的查詢將運行得更快:

select count(*) from requests use index(<index_name>); 

好像用最自然的指數是id場。

select count(*) from service_requests use index(id) 

但是這給了我以下錯誤:

ERROR 1176 (42000): Key 'id' doesn't exist in table 'requests' 

但ID不只是一個鍵,它的主鍵。在一些表格上,它是唯一的索引。爲什麼id不被視爲一個關鍵?

回答

1

要優化它,請運行optimize table,然後您可以創建另一個不是主鍵的索引,因爲InnoDB使用集羣主鍵。

創建另一個索引時,必須在易於掃描的另一個字段上創建它,而不是像文本字段(如果它適用於請求)。

錯誤 - 如果你繼續使用主鍵,而不是創造另一個指標爲準原因:

至於你提到的主鍵確實id然後使用上iduse index(id)(在表中的PK查詢來自哪裏)將不起作用,它將是USE INDEX (PRIMARY)。要查看錶的其他索引,請運行SHOW INDEX FROM <Table>命令,這將顯示錶的其他索引名稱。

進一步信息: http://dev.mysql.com/doc/refman/5.7/en/optimize-table.html http://dev.mysql.com/doc/refman/5.7/en/index-hints.html

+0

你也可以使用FORCE INDEX(PRIMARY) – cp50

0
  • 不要運行在一個InnoDB表OPTIMIZE TABLE;它幾乎從不提供任何改進。
  • 請勿使用USE INDEXFORCE INDEX,除非是最後的手段。它可能會在今天幫助你,但它可能會使明天的事情變得更糟。 Optimize動態選擇「最佳」索引,並且在其選擇中通常是「正確的」。
  • PRIMARY KEY可能是用於全表COUNT(*)的最差索引。
  • SELECT COUNT(*)需要時間(對於InnoDB),因爲它必須掃描整個表,繞過正在進行的任何事務。
  • 這樣的掃描會選擇'最小'索引,所以它可能有助於創建INDEX(foo),其中foo是一些小列。但是,這個速度不可能超過兩倍。
  • 「684s,47s,47s」 - 可能第一個請求沒有找到所有緩存在RAM中的數據,並且不得不從磁盤中獲取它。由於緩存,第二和第三速度要快得多。
  • 配置mysql的innodb_buffer_pool_size約爲可用 RAM的70%,以減少I/O。
  • 如果results中有太多行需要「太長」,那麼這個數字可能沒有意義。請注意,有些搜索引擎不再說「1,234,566個結果中的10個」,甚至不包含「大約1,000,000個結果中的10個」。那是因爲他們發現它不值得計算甚至估計。
  • 所以,你下一步(假設你不願意擺脫計數)是想出一些的方法估計緩存的數量。
  • 如果你SELECTWHERE條款,那麼我的答案大部分不適用。