日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

HBase 数据库检索性能优化策略--转

發(fā)布時間:2025/4/5 数据库 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 HBase 数据库检索性能优化策略--转 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

https://www.ibm.com/developerworks/cn/java/j-lo-HBase/index.html

HBase 數(shù)據(jù)表介紹

HBase 數(shù)據(jù)庫是一個基于分布式的、面向列的、主要用于非結(jié)構(gòu)化數(shù)據(jù)存儲用途的開源數(shù)據(jù)庫。其設(shè)計(jì)思路來源于 Google 的非開源數(shù)據(jù)庫”BigTable”。

HDFS 為 HBase 提供底層存儲支持,MapReduce 為其提供計(jì)算能力,ZooKeeper 為其提供協(xié)調(diào)服務(wù)和 failover(失效轉(zhuǎn)移的備份操作)機(jī)制。Pig 和 Hive 為 HBase 提供了高層語言支持,使其可以進(jìn)行數(shù)據(jù)統(tǒng)計(jì)(可實(shí)現(xiàn)多表 join 等),Sqoop 則為其提供 RDBMS 數(shù)據(jù)導(dǎo)入功能。

HBase 不能支持 where 條件、Order by 查詢,只支持按照主鍵 Rowkey 和主鍵的 range 來查詢,但是可以通過 HBase 提供的 API 進(jìn)行條件過濾。

HBase 的 Rowkey 是數(shù)據(jù)行的唯一標(biāo)識,必須通過它進(jìn)行數(shù)據(jù)行訪問,目前有三種方式,單行鍵訪問、行鍵范圍訪問、全表掃描訪問。數(shù)據(jù)按行鍵的方式排序存儲,依次按位比較,數(shù)值較大的排列在后,例如 int 方式的排序:1,10,100,11,12,2,20…,906,…。

ColumnFamily 是“列族”,屬于 schema 表,在建表時定義,每個列屬于一個列族,列名用列族作為前綴“ColumnFamily:qualifier”,訪問控制、磁盤和內(nèi)存的使用統(tǒng)計(jì)都是在列族層面進(jìn)行的。

Cell 是通過行和列確定的一個存儲單元,值以字節(jié)碼存儲,沒有類型。

Timestamp 是區(qū)分不同版本 Cell 的索引,64 位整型。不同版本的數(shù)據(jù)按照時間戳倒序排列,最新的數(shù)據(jù)版本排在最前面。

Hbase 在行方向上水平劃分成 N 個 Region,每個表一開始只有一個 Region,數(shù)據(jù)量增多,Region 自動分裂為兩個,不同 Region 分布在不同 Server 上,但同一個不會拆分到不同 Server。

Region 按 ColumnFamily 劃分成 Store,Store 為最小存儲單元,用于保存一個列族的數(shù)據(jù),每個 Store 包括內(nèi)存中的 memstore 和持久化到 disk 上的 HFile。

圖 1 是 HBase 數(shù)據(jù)表的示例,數(shù)據(jù)分布在多臺節(jié)點(diǎn)機(jī)器上面。

圖 1. HBase 數(shù)據(jù)表示例

HBase 調(diào)用 API 示例

類似于操作關(guān)系型數(shù)據(jù)庫的 JDBC 庫,HBase client 包本身提供了大量可以供操作的 API,幫助用戶快速操作 HBase 數(shù)據(jù)庫。提供了諸如創(chuàng)建數(shù)據(jù)表、刪除數(shù)據(jù)表、增加字段、存入數(shù)據(jù)、讀取數(shù)據(jù)等等接口。清單 1 提供了一個作者封裝的工具類,包括操作數(shù)據(jù)表、讀取數(shù)據(jù)、存入數(shù)據(jù)、導(dǎo)出數(shù)據(jù)等方法。

清單 1.HBase API 操作工具類代碼
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HColumnDescriptor; import org.apache.hadoop.hbase.HTableDescriptor; import org.apache.hadoop.hbase.KeyValue; import org.apache.hadoop.hbase.client.Get; import org.apache.hadoop.hbase.client.HBaseAdmin; import org.apache.hadoop.hbase.client.HTable; import org.apache.hadoop.hbase.client.Put; import org.apache.hadoop.hbase.client.Result; import org.apache.hadoop.hbase.client.ResultScanner; import org.apache.hadoop.hbase.client.Scan; import org.apache.hadoop.hbase.util.Bytes;import java.io.IOException; import java.util.ArrayList; import java.util.List;public class HBaseUtil { private Configuration conf = null; private HBaseAdmin admin = null;protected HBaseUtil(Configuration conf) throws IOException {this.conf = conf;this.admin = new HBaseAdmin(conf); }public boolean existsTable(String table)throws IOException {return admin.tableExists(table); }public void createTable(String table, byte[][] splitKeys, String... colfams)throws IOException { HTableDescriptor desc = new HTableDescriptor(table); for (String cf : colfams) { HColumnDescriptor coldef = new HColumnDescriptor(cf); desc.addFamily(coldef);} if (splitKeys != null) { admin.createTable(desc, splitKeys); } else { admin.createTable(desc);} }public void disableTable(String table) throws IOException { admin.disableTable(table); }public void dropTable(String table) throws IOException {if (existsTable(table)) {disableTable(table);admin.deleteTable(table);} }public void fillTable(String table, int startRow, int endRow, int numCols,int pad, boolean setTimestamp, boolean random,String... colfams) throws IOException {HTable tbl = new HTable(conf, table);for (int row = startRow; row <= endRow; row++) {for (int col = 0; col < numCols; col++) {Put put = new Put(Bytes.toBytes("row-"));for (String cf : colfams) {String colName = "col-";String val = "val-";if (setTimestamp) {put.add(Bytes.toBytes(cf), Bytes.toBytes(colName),col, Bytes.toBytes(val));} else {put.add(Bytes.toBytes(cf), Bytes.toBytes(colName),Bytes.toBytes(val));}}tbl.put(put);}}tbl.close();}public void put(String table, String row, String fam, String qual,String val) throws IOException {HTable tbl = new HTable(conf, table);Put put = new Put(Bytes.toBytes(row));put.add(Bytes.toBytes(fam), Bytes.toBytes(qual), Bytes.toBytes(val));tbl.put(put);tbl.close();}public void put(String table, String row, String fam, String qual, long ts,String val) throws IOException {HTable tbl = new HTable(conf, table);Put put = new Put(Bytes.toBytes(row));put.add(Bytes.toBytes(fam), Bytes.toBytes(qual), ts, Bytes.toBytes(val));tbl.put(put);tbl.close();}public void put(String table, String[] rows, String[] fams, String[] quals,long[] ts, String[] vals) throws IOException {HTable tbl = new HTable(conf, table);for (String row : rows) {Put put = new Put(Bytes.toBytes(row));for (String fam : fams) {int v = 0;for (String qual : quals) {String val = vals[v < vals.length ? v : vals.length];long t = ts[v < ts.length ? v : ts.length - 1];put.add(Bytes.toBytes(fam), Bytes.toBytes(qual), t,Bytes.toBytes(val));v++;}}tbl.put(put);}tbl.close();}public void dump(String table, String[] rows, String[] fams, String[] quals)throws IOException {HTable tbl = new HTable(conf, table);List<Get> gets = new ArrayList<Get>();for (String row : rows) {Get get = new Get(Bytes.toBytes(row));get.setMaxVersions();if (fams != null) {for (String fam : fams) {for (String qual : quals) {get.addColumn(Bytes.toBytes(fam), Bytes.toBytes(qual));}}}gets.add(get);}Result[] results = tbl.get(gets);for (Result result : results) {for (KeyValue kv : result.raw()) {System.out.println("KV: " + kv +", Value: " + Bytes.toString(kv.getValue()));}}}private static void scan(int caching, int batch) throws IOException {HTable table = null;final int[] counters = {0, 0};Scan scan = new Scan();scan.setCaching(caching); // co ScanCacheBatchExample-1-Set Set caching and batch parameters.scan.setBatch(batch);ResultScanner scanner = table.getScanner(scan);for (Result result : scanner) {counters[1]++; // co ScanCacheBatchExample-2-Count Count the number of Results available.}scanner.close();System.out.println("Caching: " + caching + ", Batch: " + batch +", Results: " + counters[1] + ", RPCs: " + counters[0]);} }

操作表的 API 都有 HBaseAdmin 提供,特別講解一下 Scan 的操作部署。

HBase 的表數(shù)據(jù)分為多個層次,HRegion->HStore->[HFile,HFile,...,MemStore]。

在 HBase 中,一張表可以有多個 Column Family,在一次 Scan 的流程中,每個 Column Family(Store) 的數(shù)據(jù)讀取由一個 StoreScanner 對象負(fù)責(zé)。每個 Store 的數(shù)據(jù)由一個內(nèi)存中的 MemStore 和磁盤上的 HFile 文件組成,對應(yīng)的 StoreScanner 對象使用一個 MemStoreScanner 和 N 個 StoreFileScanner 來進(jìn)行實(shí)際的數(shù)據(jù)讀取。

因此,讀取一行的數(shù)據(jù)需要以下步驟:

1. 按照順序讀取出每個 Store

2. 對于每個 Store,合并 Store 下面的相關(guān)的 HFile 和內(nèi)存中的 MemStore

這兩步都是通過堆來完成。RegionScanner 的讀取通過下面的多個 StoreScanner 組成的堆完成,使用 RegionScanner 的成員變量 KeyValueHeap storeHeap 表示。一個 StoreScanner 一個堆,堆中的元素就是底下包含的 HFile 和 MemStore 對應(yīng)的 StoreFileScanner 和 MemStoreScanner。堆的優(yōu)勢是建堆效率高,可以動態(tài)分配內(nèi)存大小,不必事先確定生存周期。

接著調(diào)用 seekScanners() 對這些 StoreFileScanner 和 MemStoreScanner 分別進(jìn)行 seek。seek 是針對 KeyValue 的,seek 的語義是 seek 到指定 KeyValue,如果指定 KeyValue 不存在,則 seek 到指定 KeyValue 的下一個。

Scan類常用方法說明

scan.addFamily()/scan.addColumn():指定需要的 Family 或 Column,如果沒有調(diào)用任何 addFamily 或 Column,會返回所有的 Columns;

scan.setMaxVersions():指定最大的版本個數(shù)。如果不帶任何參數(shù)調(diào)用 setMaxVersions,表示取所有的版本。如果不掉用 setMaxVersions,只會取到最新的版本.;

scan.setTimeRange():指定最大的時間戳和最小的時間戳,只有在此范圍內(nèi)的 Cell 才能被獲取;

scan.setTimeStamp():指定時間戳;

scan.setFilter():指定 Filter 來過濾掉不需要的信息;

scan.setStartRow():指定開始的行。如果不調(diào)用,則從表頭開始;

scan.setStopRow():指定結(jié)束的行(不含此行);

scan. setCaching():每次從服務(wù)器端讀取的行數(shù)(影響 RPC);

scan.setBatch():指定最多返回的 Cell 數(shù)目。用于防止一行中有過多的數(shù)據(jù),導(dǎo)致 OutofMemory 錯誤,默認(rèn)無限制。

HBase 數(shù)據(jù)表優(yōu)化

HBase 是一個高可靠性、高性能、面向列、可伸縮的分布式數(shù)據(jù)庫,但是當(dāng)并發(fā)量過高或者已有數(shù)據(jù)量很大時,讀寫性能會下降。我們可以采用如下方式逐步提升 HBase 的檢索速度。

預(yù)先分區(qū)

默認(rèn)情況下,在創(chuàng)建 HBase 表的時候會自動創(chuàng)建一個 Region 分區(qū),當(dāng)導(dǎo)入數(shù)據(jù)的時候,所有的 HBase 客戶端都向這一個 Region 寫數(shù)據(jù),直到這個 Region 足夠大了才進(jìn)行切分。一種可以加快批量寫入速度的方法是通過預(yù)先創(chuàng)建一些空的 Regions,這樣當(dāng)數(shù)據(jù)寫入 HBase 時,會按照 Region 分區(qū)情況,在集群內(nèi)做數(shù)據(jù)的負(fù)載均衡。

Rowkey 優(yōu)化

HBase 中 Rowkey 是按照字典序存儲,因此,設(shè)計(jì) Rowkey 時,要充分利用排序特點(diǎn),將經(jīng)常一起讀取的數(shù)據(jù)存儲到一塊,將最近可能會被訪問的數(shù)據(jù)放在一塊。

此外,Rowkey 若是遞增的生成,建議不要使用正序直接寫入 Rowkey,而是采用 reverse 的方式反轉(zhuǎn) Rowkey,使得 Rowkey 大致均衡分布,這樣設(shè)計(jì)有個好處是能將 RegionServer 的負(fù)載均衡,否則容易產(chǎn)生所有新數(shù)據(jù)都在一個 RegionServer 上堆積的現(xiàn)象,這一點(diǎn)還可以結(jié)合 table 的預(yù)切分一起設(shè)計(jì)。

減少ColumnFamily 數(shù)量

不要在一張表里定義太多的 ColumnFamily。目前 Hbase 并不能很好的處理超過 2~3 個 ColumnFamily 的表。因?yàn)槟硞€ ColumnFamily 在 flush 的時候,它鄰近的 ColumnFamily 也會因關(guān)聯(lián)效應(yīng)被觸發(fā) flush,最終導(dǎo)致系統(tǒng)產(chǎn)生更多的 I/O。

緩存策略 (setCaching)

創(chuàng)建表的時候,可以通過 HColumnDescriptor.setInMemory(true) 將表放到 RegionServer 的緩存中,保證在讀取的時候被 cache 命中。

設(shè)置存儲生命期

創(chuàng)建表的時候,可以通過 HColumnDescriptor.setTimeToLive(int timeToLive) 設(shè)置表中數(shù)據(jù)的存儲生命期,過期數(shù)據(jù)將自動被刪除。

硬盤配置

每臺 RegionServer 管理 10~1000 個 Regions,每個 Region 在 1~2G,則每臺 Server 最少要 10G,最大要 1000*2G=2TB,考慮 3 備份,則要 6TB。方案一是用 3 塊 2TB 硬盤,二是用 12 塊 500G 硬盤,帶寬足夠時,后者能提供更大的吞吐率,更細(xì)粒度的冗余備份,更快速的單盤故障恢復(fù)。

分配合適的內(nèi)存給 RegionServer 服務(wù)

在不影響其他服務(wù)的情況下,越大越好。例如在 HBase 的 conf 目錄下的 hbase-env.sh 的最后添加 export HBASE_REGIONSERVER_OPTS="-Xmx16000m $HBASE_REGIONSERVER_OPTS”

其中 16000m 為分配給 RegionServer 的內(nèi)存大小。

寫數(shù)據(jù)的備份數(shù)

備份數(shù)與讀性能成正比,與寫性能成反比,且備份數(shù)影響高可用性。有兩種配置方式,一種是將 hdfs-site.xml 拷貝到 hbase 的 conf 目錄下,然后在其中添加或修改配置項(xiàng) dfs.replication 的值為要設(shè)置的備份數(shù),這種修改對所有的 HBase 用戶表都生效,另外一種方式,是改寫 HBase 代碼,讓 HBase 支持針對列族設(shè)置備份數(shù),在創(chuàng)建表時,設(shè)置列族備份數(shù),默認(rèn)為 3,此種備份數(shù)只對設(shè)置的列族生效。

WAL(預(yù)寫日志)

可設(shè)置開關(guān),表示 HBase 在寫數(shù)據(jù)前用不用先寫日志,默認(rèn)是打開,關(guān)掉會提高性能,但是如果系統(tǒng)出現(xiàn)故障 (負(fù)責(zé)插入的 RegionServer 掛掉),數(shù)據(jù)可能會丟失。配置 WAL 在調(diào)用 Java API 寫入時,設(shè)置 Put 實(shí)例的 WAL,調(diào)用 Put.setWriteToWAL(boolean)。

批量寫

HBase 的 Put 支持單條插入,也支持批量插入,一般來說批量寫更快,節(jié)省來回的網(wǎng)絡(luò)開銷。在客戶端調(diào)用 Java API 時,先將批量的 Put 放入一個 Put 列表,然后調(diào)用 HTable 的 Put(Put 列表) 函數(shù)來批量寫。

客戶端一次從服務(wù)器拉取的數(shù)量

通過配置一次拉去的較大的數(shù)據(jù)量可以減少客戶端獲取數(shù)據(jù)的時間,但是它會占用客戶端內(nèi)存。有三個地方可進(jìn)行配置:

1)在 HBase 的 conf 配置文件中進(jìn)行配置 hbase.client.scanner.caching;

2)通過調(diào)用 HTable.setScannerCaching(int scannerCaching) 進(jìn)行配置;

3)通過調(diào)用 Scan.setCaching(int caching) 進(jìn)行配置。三者的優(yōu)先級越來越高。

RegionServer 的請求處理 IO 線程數(shù)

較少的 IO 線程適用于處理單次請求內(nèi)存消耗較高的 Big Put 場景 (大容量單次 Put 或設(shè)置了較大 cache 的 Scan,均屬于 Big Put) 或 ReigonServer 的內(nèi)存比較緊張的場景。

較多的 IO 線程,適用于單次請求內(nèi)存消耗低,TPS 要求 (每秒事務(wù)處理量 (TransactionPerSecond)) 非常高的場景。設(shè)置該值的時候,以監(jiān)控內(nèi)存為主要參考。

在 hbase-site.xml 配置文件中配置項(xiàng)為 hbase.regionserver.handler.count。

Region 大小設(shè)置

配置項(xiàng)為 hbase.hregion.max.filesize,所屬配置文件為 hbase-site.xml.,默認(rèn)大小 256M。

在當(dāng)前 ReigonServer 上單個 Reigon 的最大存儲空間,單個 Region 超過該值時,這個 Region 會被自動 split 成更小的 Region。小 Region 對 split 和 compaction 友好,因?yàn)椴鸱?Region 或 compact 小 Region 里的 StoreFile 速度很快,內(nèi)存占用低。缺點(diǎn)是 split 和 compaction 會很頻繁,特別是數(shù)量較多的小 Region 不停地 split, compaction,會導(dǎo)致集群響應(yīng)時間波動很大,Region 數(shù)量太多不僅給管理上帶來麻煩,甚至?xí)l(fā)一些 Hbase 的 bug。一般 512M 以下的都算小 Region。大 Region 則不太適合經(jīng)常 split 和 compaction,因?yàn)樽鲆淮?compact 和 split 會產(chǎn)生較長時間的停頓,對應(yīng)用的讀寫性能沖擊非常大。

此外,大 Region 意味著較大的 StoreFile,compaction 時對內(nèi)存也是一個挑戰(zhàn)。如果你的應(yīng)用場景中,某個時間點(diǎn)的訪問量較低,那么在此時做 compact 和 split,既能順利完成 split 和 compaction,又能保證絕大多數(shù)時間平穩(wěn)的讀寫性能。compaction 是無法避免的,split 可以從自動調(diào)整為手動。只要通過將這個參數(shù)值調(diào)大到某個很難達(dá)到的值,比如 100G,就可以間接禁用自動 split(RegionServer 不會對未到達(dá) 100G 的 Region 做 split)。再配合 RegionSplitter 這個工具,在需要 split 時,手動 split。手動 split 在靈活性和穩(wěn)定性上比起自動 split 要高很多,而且管理成本增加不多,比較推薦 online 實(shí)時系統(tǒng)使用。內(nèi)存方面,小 Region 在設(shè)置 memstore 的大小值上比較靈活,大 Region 則過大過小都不行,過大會導(dǎo)致 flush 時 app 的 IO wait 增高,過小則因 StoreFile 過多影響讀性能。

HBase 配置

建議 HBase 的服務(wù)器內(nèi)存至少 32G,表 1 是通過實(shí)踐檢驗(yàn)得到的分配給各角色的內(nèi)存建議值。

表 1. HBase 相關(guān)服務(wù)配置信息
模塊服務(wù)種類內(nèi)存需求

HBase 的單個 Region 大小建議設(shè)置大一些,推薦 2G,RegionServer 處理少量的大 Region 比大量的小 Region 更快。對于不重要的數(shù)據(jù),在創(chuàng)建表時將其放在單獨(dú)的列族內(nèi),并且設(shè)置其列族備份數(shù)為 2(默認(rèn)是這樣既保證了雙備份,又可以節(jié)約空間,提高寫性能,代價(jià)是高可用性比備份數(shù)為 3 的稍差,且讀性能不如默認(rèn)備份數(shù)的時候。

實(shí)際案例

項(xiàng)目要求可以刪除存儲在 HBase 數(shù)據(jù)表中的數(shù)據(jù),數(shù)據(jù)在 HBase 中的 Rowkey 由任務(wù) ID(數(shù)據(jù)由任務(wù)產(chǎn)生) 加上 16 位隨機(jī)數(shù)組成,任務(wù)信息由單獨(dú)一張表維護(hù)。圖 2 所示是數(shù)據(jù)刪除流程圖。

圖 2. 數(shù)據(jù)刪除流程圖

最初的設(shè)計(jì)是在刪除任務(wù)的同時按照任務(wù) ID 刪除該任務(wù)存儲在 HBase 中的相應(yīng)數(shù)據(jù)。但是 HBase 數(shù)據(jù)較多時會導(dǎo)致刪除耗時較長,同時由于磁盤 I/O 較高,會導(dǎo)致數(shù)據(jù)讀取、寫入超時。

查看 HBase 日志發(fā)現(xiàn)刪除數(shù)據(jù)時,HBase 在做 Major Compaction 操作。Major Compaction 操作的目的是合并文件,并清除刪除、過期、多余版本的數(shù)據(jù)。Major Compaction 時 HBase 將合并 Region 中 StoreFile,該動作如果持續(xù)長時間會導(dǎo)致整個 Region 都不可讀,最終導(dǎo)致所有基于這些 Region 的查詢超時。

如果想要解決 Major Compaction 問題,需要查看它的源代碼。通過查看 HBase 源碼發(fā)現(xiàn) RegionServer 在啟動時候,有個 CompactionChecker 線程在定期檢測是否需要做 Compact。源代碼如圖 3 所示。

圖 3. CompactionChecker 線程代碼圖

isMajorCompaction 中會根據(jù) hbase.hregion.majorcompaction 參數(shù)來判斷是否做 Major Compact。如果 hbase.hregion.majorcompaction 為 0,則返回 false。修改配置文件 hbase.hregion.majorcompaction 為 0,禁止 HBase 的定期 Major Compaction 機(jī)制,通過自定義的定時機(jī)制 (在凌晨 HBase 業(yè)務(wù)不繁忙時) 執(zhí)行 Major 操作,這個定時可以是通過 Linux cron 定時啟動腳本,也可以通過 Java 的 timer?schedule,在實(shí)際項(xiàng)目中使用 Quartz 來啟動,啟動的時間配置在配置文件中給出,可以方便的修改 Major Compact 啟動的時間。通過這種修改后,我們發(fā)現(xiàn)在刪除數(shù)據(jù)后仍會有 Compact 操作。這樣流程進(jìn)入 needsCompaction = true 的分支。查看 needsCompaction 判斷條件為 (storefiles.size() - filesCompacting.size()) > minFilesToCompact 觸發(fā)。同時當(dāng)需緊縮的文件數(shù)等于 Store 的所有文件數(shù),Minor Compact 自動升級為 Major Compact。但是 Compact 操作不能禁止,因?yàn)檫@樣會導(dǎo)致數(shù)據(jù)一直存在,最終影響查詢效率。

基于以上分析,我們必須重新考慮刪除數(shù)據(jù)的流程。對用戶來說,用戶只要在檢索時對于刪除的任務(wù)不進(jìn)行檢索即可。那么只需要刪除該條任務(wù)記錄,對于該任務(wù)相關(guān)聯(lián)的數(shù)據(jù)不需要立馬進(jìn)行刪除。當(dāng)系統(tǒng)空閑時候再去定時刪除 HBase 數(shù)據(jù)表中的數(shù)據(jù),并對 Region 做 Major Compact,清理已經(jīng)刪除的數(shù)據(jù)。通過對任務(wù)刪除流程的修改,達(dá)到項(xiàng)目的需求,同時這種修改也不需要修改 HBase 的配置。

圖 4. 數(shù)據(jù)刪除流程對比圖

檢索、查詢、刪除 HBase 數(shù)據(jù)表中的數(shù)據(jù)本身存在大量的關(guān)聯(lián)性,需要查看 HBase 數(shù)據(jù)表的源代碼才能確定導(dǎo)致檢索性能瓶頸的根本原因及最終解決方案。

結(jié)束語

HBase 數(shù)據(jù)庫的使用及檢索優(yōu)化方式均與傳統(tǒng)關(guān)系型數(shù)據(jù)庫存在較多不同,本文從數(shù)據(jù)表的基本定義方式出發(fā),通過 HBase 自身提供的 API 訪問方式入手,舉例說明優(yōu)化方式及注意事項(xiàng),最后通過實(shí)例來驗(yàn)證優(yōu)化方案可行性。檢索性能本身是數(shù)據(jù)表設(shè)計(jì)、程序設(shè)計(jì)、邏輯設(shè)計(jì)等的結(jié)合產(chǎn)物,需要程序員深入理解后才能做出正確的優(yōu)化方案。

轉(zhuǎn)載于:https://www.cnblogs.com/davidwang456/p/8302565.html

總結(jié)

以上是生活随笔為你收集整理的HBase 数据库检索性能优化策略--转的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 日日摸日日碰夜夜爽无码 | 无码国产精品久久一区免费 | 91视色 | 日韩在线一级片 | 色偷偷视频 | 色综合天天干 | 黄网站免费看 | 伊人成人22| 亚洲视频在线观看网站 | 精品1区2区 | 日本黄色大片免费看 | 中文字幕亚洲欧美日韩 | 99r精品视频| 欧美国产一级片 | 久久看视频 | 欧美精品一区二区成人 | 91免费 看片| 992tv在线影院| 三级黄色生活片 | 亚洲一区二区三区在线观看视频 | 日产精品久久久久 | 久久精品a亚洲国产v高清不卡 | 99日精品 | 亚洲精品久久久 | 91精品国产日韩91久久久久久 | 可以直接在线观看的av | 欧美性aaa | 亚洲大片精品 | 在线免费观看视频黄 | 国产三级精品在线观看 | 欧美中文字幕在线观看 | 欧美成人天堂 | 精品一区二区三区精华液 | 全部免费毛片 | 中文 日韩 欧美 | 国产激情一区二区三区在线观看 | 激情综合五月天 | 久久午夜精品人妻一区二区三区 | 欧美大片xxxx | 少妇高潮惨叫久久久久 | 欧美精品一级二级三级 | 久久精品亚洲a | 伦理欧美| 欧美日p视频| 亚洲精品二区 | 欧美在线观看视频一区 | 91视频.com| 国产伦精品一区二区三区88av | 国产成人精品亚洲线观看 | 欧美激情视频一区二区三区在线播放 | 男人喷出精子视频 | 中文久久乱码一区二区 | 毛片a级片 | 日本特级黄色 | 四虎成人免费视频 | 日韩深夜在线 | 天天色天天搞 | 亚洲v在线 | 日本护士做爰视频 | 欧美日性视频 | 91五月天| 国产91小视频 | 色哟哟网站在线观看 | 日韩视频在线视频 | 国产二区精品视频 | 强睡邻居人妻中文字幕 | 少女国产免费观看 | 一区二区三区四区久久 | 成人国产精品免费 | 围产精品久久久久久久 | 色小姐在线视频 | 国产免费脚交足视频在线观看 | 欧美亚洲第一区 | 国产尻逼视频 | 国产精品一区在线播放 | 天天色天天爱 | 女女高潮h冰块play失禁百合 | 久久久久久久久久久久久久久久久 | 青青草原伊人网 | 日韩视频精品 | 91最新地址永久入口 | 四虎在线播放 | 婷婷激情电影 | 国产欧美一区二区视频 | 夜夜撸av | 挪威xxxx性hd极品 | 在线视频欧美亚洲 | 粗大黑人巨茎大战欧美成人 | 日本高清有码 | 97超碰人人澡 | 久久视频在线观看免费 | 国产精品jizz在线观看美国 | 综合激情亚洲 | 三级国产视频 | 操人视频免费 | 永久免费未满 | 免费看黄在线观看 | 91文字幕巨乱亚洲香蕉 | 动漫美女被吸乳奶动漫视频 |