8

我有一些查詢花費的時間太長(300ms),現在數據庫已經增長到幾百萬條記錄。幸運的是,查詢不需要查看大部分數據,最新的100,000條記錄就足夠了,因此我的計劃是維護一個包含最近100,000條記錄的單獨表格,並針對此進行查詢。如果任何人有任何建議,以更好的方式做到這一點很好。我真正的問題是,如果查詢確實需要針對歷史數據運行,那麼有什麼選擇?下一步是什麼?我想過的東西:我已經遇到了數據庫性能瓶頸,現在呢?

  • 升級硬件
  • 內存數據庫手動
  • 緩存中的對象在自己的數據結構使用的

這些東西是正確的,是否有任何其他選擇?一些DB提供者是否比其他人有更多的功能來處理這些問題,例如指定一個特定的表/索引完全在內存中?

對不起,我應該提到這一點,我正在使用mysql。

我忘了在上面提到索引。到目前爲止,索引一直是我唯一的改進來源,相當誠實。爲了找出瓶頸,我一直在使用maatkit查詢來顯示索引是否被利用。

我知道我現在已經遠離了問題的目的,所以也許我應該再做一個。我的問題是EXPLAIN說這個查詢需要10ms而不是jmsofiler報告的300ms。如果有人有任何建議,我會很感激。查詢是:

select bv.* 
from BerthVisit bv 
inner join BerthVisitChainLinks on bv.berthVisitID = BerthVisitChainLinks.berthVisitID 
inner join BerthVisitChain on BerthVisitChainLinks.berthVisitChainID = BerthVisitChain.berthVisitChainID 
inner join BerthJourneyChains on BerthVisitChain.berthVisitChainID = BerthJourneyChains.berthVisitChainID 
inner join BerthJourney on BerthJourneyChains.berthJourneyID = BerthJourney.berthJourneyID 
inner join TDObjectBerthJourneyMap on BerthJourney.berthJourneyID = TDObjectBerthJourneyMap.berthJourneyID 
inner join TDObject on TDObjectBerthJourneyMap.tdObjectID = TDObject.tdObjectID 
where 
BerthJourney.journeyType='A' and 
bv.berthID=251860 and 
TDObject.headcode='2L32' and 
bv.depTime is null and 
bv.arrTime > '2011-07-28 16:00:00' 

,並從EXPLAIN輸出:

+----+-------------+-------------------------+-------------+---------------------------------------------+-------------------------+---------+------------------------------------------------+------+-------------------------------------------------------+ 
| id | select_type | table     | type  | possible_keys        | key      | key_len | ref           | rows | Extra             | 
+----+-------------+-------------------------+-------------+---------------------------------------------+-------------------------+---------+------------------------------------------------+------+-------------------------------------------------------+ 
| 1 | SIMPLE  | bv      | index_merge | PRIMARY,idx_berthID,idx_arrTime,idx_depTime | idx_berthID,idx_depTime | 9,9  | NULL           | 117 | Using intersect(idx_berthID,idx_depTime); Using where | 
| 1 | SIMPLE  | BerthVisitChainLinks | ref   | idx_berthVisitChainID,idx_berthVisitID  | idx_berthVisitID  | 8  | Network.bv.berthVisitID      | 1 | Using where           | 
| 1 | SIMPLE  | BerthVisitChain   | eq_ref  | PRIMARY          | PRIMARY     | 8  | Network.BerthVisitChainLinks.berthVisitChainID | 1 | Using where; Using index        | 
| 1 | SIMPLE  | BerthJourneyChains  | ref   | idx_berthJourneyID,idx_berthVisitChainID | idx_berthVisitChainID | 8  | Network.BerthVisitChain.berthVisitChainID  | 1 | Using where           | 
| 1 | SIMPLE  | BerthJourney   | eq_ref  | PRIMARY,idx_journeyType      | PRIMARY     | 8  | Network.BerthJourneyChains.berthJourneyID  | 1 | Using where           | 
| 1 | SIMPLE  | TDObjectBerthJourneyMap | ref   | idx_tdObjectID,idx_berthJourneyID   | idx_berthJourneyID  | 8  | Network.BerthJourney.berthJourneyID   | 1 | Using where           | 
| 1 | SIMPLE  | TDObject    | eq_ref  | PRIMARY,idx_headcode      | PRIMARY     | 8  | Network.TDObjectBerthJourneyMap.tdObjectID  | 1 | Using where           | 
+----+-------------+-------------------------+-------------+---------------------------------------------+-------------------------+---------+------------------------------------------------+------+--------------------------------------- 

7 rows in set (0.01 sec) 
+3

您正在使用哪種RDBMS? –

+3

EXPLAIN PLAN在哪裏說瓶頸是你的麻煩問題? –

+5

「所以我的計劃是用最近的100,000條記錄維護一個單獨的表並且針對這個查詢運行查詢」 - 聽起來像個壞主意。 –

回答

1

考慮到這樣的設計變化並不是一個好兆頭 - 我敢打賭,你仍然有很多性能來擠壓使用EXPLAIN,調整數據庫變量和改進索引和查詢。但是你可能已經過去了「嘗試東西」的工作得很好。這是一個學習如何解釋分析和日誌的機會,並且可以使用您學習的針對索引和查詢的具體改進。

如果你的建議是一個好的建議,你應該能夠告訴我們爲什麼已經。並指出,這是一個受歡迎的pessimization--

What is the most ridiculous pessimization you've seen?

3
  1. 確保所有的指標都進行了優化。在查詢上使用explain以查看它是否有效地使用索引。
  2. 如果你正在做一些沉重的連接,然後開始考慮在java中做這個計算。
  3. 想想使用其他數據庫如NoSQL。您可能可以進行一些預處理,並將數據放入Memcache中以幫助您一點。
+0

同意。沒有提及索引,並且在大表上提供了巨大的性能提升:http://stackoverflow.com/questions/1108/how-does-database-indexing-work –

+0

更改數據庫並不是每個人的選擇。 – abhi

+0

我不是說改變DB。我正在說使用另一個數據庫臨時緩存數據。 –

0

我會先嚐試優化表/索引/查詢之前採取任何您列出的措施。您是否深入瞭解了性能不佳的查詢,以至於您完全相信您已達到RDBMS功能的極限?

編輯:如果您確實進行了正確優化但仍有問題,請考慮爲您需要的確切數據創建物化視圖。基於比您提供的因素更多的因素,這可能是也可能不是一個好主意,但我會把它列在要考慮的事項清單的頂部。

+0

創建視圖會很好 – woliveirajr

0

在最近的100,000條記錄中搜索應該非常快,你肯定有索引問題。使用EXPLAIN並修復它。

+1

要清楚的是,目前需要300ms的查詢約爲900萬。我的想法是將900萬降至10萬以使其更快。只要您擁有正確的索引, – James

+0

大小無關緊要。如果您僅在最近100,000次搜索,那麼其中有8,900,000個其他記錄並不重要。如果仍有疑問,請發佈您的查詢和數據庫架構。 –

1

好吧,如果你已經優化了數據庫和查詢,我會說,而不是砍了數據,下一步是看:

一)mysql的配置,並確保它是充分利用硬件

b)看硬件。你不會說你使用的是什麼硬件。如果您可以購買兩臺或三臺服務器來分隔數據庫中的讀取數據(寫入操作必須完成到中央服務器,但讀取數據可以從任意數量的從服務器中讀取),那麼您可能會發現複製是您的一種選擇。 。

1

而是創造了最新的結果單獨的表,想想表分區。 MySQL自5.1版以來內置此功能


只是爲了說清楚:我不是說這是您的問題的解決方案。只有一件事你可以嘗試

0

我明白我現在已經遠離了問題的目的是爲了 所以也許我應該再做一個。我的問題是,EXPLAIN說 查詢需要10ms,而不是jprofiler報告的300ms。

然後你的問題(和解決方案)必須在Java中,對吧?