影響資料檢索效率的幾個因素(1)

來源:互聯網
上載者:User

影響資料檢索效率的幾個因素(1)

資料檢索有兩種主要形態。第一種是純資料庫型的。典型的結構是一個關係型資料,比如 mysql。使用者通過 SQL 表達出所需要的資料,mysql 把 SQL 翻譯成物理的資料檢索動作返回結果。第二種形態是現在越來越流行的大資料玩家的玩法。典型的結構是有一個分區的資料存放區,最初這種儲存就是原始的 HDFS,後來開逐步有人在 HDFS 上加上索引的支援,或者乾脆用 Elasticsearc 這樣的資料存放區。然後在儲存之上有一個分布式的Realtime Compute層,比如 Hive 或者 Spark SQL。使用者用 Hive SQL 提交給計算層,計算層從儲存裡拉取出資料,進行計算之後返回給使用者。這種大資料的玩法起初是因為 SQL 有很多 ad-hoc 查詢是滿足不了的,乾脆讓使用者自己寫 map/reduce 想怎麼算都可以了。但是後來玩大了之後,越來越多的人覺得這些 Hive 之類的方案查詢效率怎麼那麼低下啊。於是一個又一個項目開始去最佳化這些大資料計算架構的查詢效能。這些最佳化手段和經典的資料庫最佳化到今天的手段是沒有什麼兩樣的,很多公司打著搞計算引擎的旗號乾著重新發明資料庫的活。所以,迴歸本質,影響資料檢索效率的就那麼幾個因素。我們不妨來看一看。

資料檢索乾的是什麼事情

定位 => 載入 => 變換

找到所需要的資料,把資料從遠程或者磁碟載入到記憶體中。按照規則進行變換,比如按某個欄位group by,取另外一個欄位的sum之類的計算。

影響效率的四個因素

  • 讀取更少的資料
  • 資料本地化,充分遵循底層硬體的限制設計架構
  • 更多的機器
  • 更高效率的計算和計算的物理實現

原則上的四點描述是非常抽象的。我們具體來看這些點映射到實際的資料庫中都是一些什麼樣的最佳化措施。

讀取更少的資料

資料越少,檢索需要的時間當然越少了。在考慮所有技術手段之前,最有效果的恐怕是從業務的角度審視一下我們是否需要從那麼多的資料中檢索出結果來。有沒有可能用更少的資料達到同樣的效果。減少的資料量的兩個手段,彙總和抽樣。如果在入庫之前把資料就做了彙總或者抽樣,是不是可以極大地減少查詢所需要的時間,同時效果上並無多少差異呢?極端情況下,如果需要的是一天的總訪問量,比如有1個億。查詢的時候去數1億行肯定快不了。但是如果統計好了一天的總訪問量,查詢的時候只需要取得一條記錄就可以知道今天有1個億的人訪問了。

索引是一種非常常見的減少資料讀取量的策略了。一般的按行儲存的關係型資料庫都會有一個主鍵。用這個主鍵可以非常快速的尋找到對應的行。KV儲存也是這樣,按照Key可以快速地找到對應的Value。可以理解為一個Hashmap。但是一旦查詢的時候不是用主鍵,而是另外一個欄位。那麼最糟糕的情況就是進行一次全表的掃描了,也就是把所有的資料都讀取出來,然後看要的資料到底在哪裡,這就不可能快了。減少資料讀取量的最佳方案就是,建立一個類似字典一樣的尋找表,當我們找 username=wentao 的時候,可以列舉出所有有 wentao 作為使用者名稱的行的主鍵。然後拿這些主鍵去行儲存(就是那個hashmap)裡撈資料,就一撈一個準了。

談到索引就不得不談一下一個查詢使用了兩個欄位,如何使用兩個索引的問題。mysql的行為可以代表大部分主流資料庫的處理方式:

https://www.percona.com/blog/2012/12/14/the-optimization-that-often-is...

https://www.percona.com/blog/2014/01/03/multiple-column-index-vs-multi...

基本上來說,經驗表明有多個單欄位的索引,最後資料庫會選一最優的來使用。其餘欄位的過濾仍然是通過資料讀取到記憶體之後,用predicate去判斷的。也就是無法減少資料的讀取量。

在這個方面基於inverted index的資料就非常有特點。一個是Elasticsearch為代表的lucene系的資料庫。另外一個是新銳的druid資料庫。

https://www.found.no/foundation/elasticsearch-from-the-bottom-up/

http://druid.io/blog/2012/09/21/druid-bitmap-compression.html

效果就是,這些資料庫可以把單欄位的filter結果緩衝起來。多個欄位的查詢可以把之前緩衝的結果直接拿過來做 AND 或者 OR 操作。

索引存在的必要是因為主儲存沒有提供直接的快速定位的能力。如果訪問的就是資料庫的主鍵,那麼需要讀取的資料也就非常少了。另外一個變種就是支援遍曆的主鍵,比如hbase的rowkey。如果查詢的是一個基於rowkey的範圍,那麼像hbase這樣的資料庫就可以支援唯讀取到這個範圍內的資料,而不用讀取不再這個範圍內的額外資料,從而提高速度。這種加速的方式就是利用了主儲存自身的物理分布的特性。另外一個更常見的情境就是 partition。比如 mysql 或者 postgresql 都支援分區表的概念。當我們建立了分區表之後,尋找的條件如果可以過濾出分區,那麼可以大幅減少需要讀取的資料量。比 partition 更細粒度一些的是 clustered index。它其實不是一個索引(二級索引),它是改變了資料在主儲存內的相片順序,讓相同clustered key的資料彼此緊挨著放在一起,從而在查詢的時候避免掃描到無關的資料。比 partition 更粗一些的是分庫分表分檔案。比如我們可以一天建立一張表,查詢的時候先定位到表,再執行 SQL。比如 graphite 給每個 metric 建立一個檔案存放採集來的 data point,查詢的時候給定metric 就可以定位到一個檔案,然後唯讀取這個檔案的資料。


相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.