簡體   English   中英

Cassandra閱讀/獲得表現

[英]Cassandra Read/Get Performance

我的Cassandra表具有以下模式

CREATE TABLE cachetable1 (
id text,
lsn text,
lst timestamp,
PRIMARY KEY ((id))
) WITH
bloom_filter_fp_chance=0.010000 AND
caching='{"keys":"ALL", "rows_per_partition":"ALL"}' AND
comment='' AND
dclocal_read_repair_chance=0.100000 AND
gc_grace_seconds=864000 AND
read_repair_chance=0.000000 AND
default_time_to_live=0 AND
speculative_retry='99.0PERCENTILE' AND
memtable_flush_period_in_ms=0 AND
compaction={'class': 'SizeTieredCompactionStrategy'} AND
compression={'sstable_compression': 'LZ4Compressor'};

上表包含221百萬行(約16 GB數據)。 CassandraDaemon以4GB堆空間運行,我為行緩存配置了4 GB內存。 我試着從我的java代碼中運行select查詢

for(int i = 0; i < 1000; i ++)
    {
        int id = random.nextInt(20000000 - 0) + 0;
        for(j = id; j <= id + 100; j++)
        {
            ls.add(j+"");
        }

           Statement s = QueryBuilder.select("lst","lsn").from("ks1" , "cachetable1").where(QueryBuilder.in("id",ls.toArray()));
           s.setFetchSize(100);

               ResultSet rs=sess.execute( s );
              List<Row> lsr=rs.all();
               for(Row rw:lsr)
               {
                   //System.out.println(rw.toString());
                   count++;
               }

        ls.clear();
    }

在上面的代碼中,我試圖獲取0.1百萬條記錄。 但是讀取/獲取性能非常糟糕。 獲取0.1百萬行需要400-500秒。 有沒有更好的方法通過Java從Cassandra讀取/獲取記錄? 除了行緩存大小和Cassandra堆大小之外還需要一些調整嗎?

您似乎想要以100行塊的形式檢索數據。 這聽起來像是聚類列的一個很好的候選者。

更改架構以使用id作為分區鍵,將塊索引用作聚類列,即PRIMARY KEY((id),chunk_idx)。 插入數據時,您必須弄清楚如何將單個索引映射到id和chunk_idx(例如,可能在您的某個值上執行模100以生成chunk_idx)。

現在,當您查詢id並且未指定chunk_idx時,Cassandra可以有效地返回所有100行,並在分區上讀取一個磁盤。 如果您不總是想要讀取整塊行,那么通過指定chunk_idx,您仍然可以在分區內執行范圍查詢和單行檢索。

所以你的錯誤是你在每個查詢中產生100個隨機分區讀取,這將擊中所有節點並需要為每個節點單獨讀取一個磁盤。 請記住,僅僅因為您查詢順序索引號並不意味着數據存儲在一起,而且與Cassandra完全相反,順序分區鍵可能存儲在不同的節點上。

您正在犯的第二個錯誤是您正在同步執行查詢(即您在發出更多查詢之前發出查詢並等待請求完成)。 您要做的是使用線程池,以便您可以並行運行許多查詢,或者在單個線程中使用executeAsync方法。 由於您的查詢效率不高,等待100個隨機分區讀取完成將是一個漫長的等待,並且很多高度流水線化的Cassandra容量將坐在那里歪着拇指等待某事做。 如果您嘗試最大限度地提高性能,則希望盡可能使所有節點保持忙碌狀態。

另一件需要考慮的事情是在連接到集群時使用TokenAwarePolicy。 這允許每個查詢直接進入具有分區副本的節點,而不是可能必須充當協調器的隨機節點,並通過額外的躍點獲取數據。 當然,在讀取時使用一致性級別ONE比一致性級別更高。

行緩存大小和堆大小不是問題的根源,因此這是錯誤的路徑。

我猜這是你的罪魁禍首:

.where(QueryBuilder.in("id",ls.toArray()))

眾所周知,在WHERE子句中使用IN關系是不具有性能的。 在某些情況下,執行許多並行查詢可能比使用一個IN查詢更快。 DataStax SELECT文檔

何時不使用IN

...使用IN會降低性能,因為通常必須查詢許多節點。 例如,在具有30個節點,復制因子為3且一致性級別為LOCAL_QUORUM的單個本地數據中心集群中,單個密鑰查詢將發送到兩個節點,但如果查詢使用IN條件,則數量為被查詢的節點很可能甚至更高,最多20個節點,具體取決於密鑰落在令牌范圍內的位置。

所以你有兩個選擇(假設生活在這個表現不佳的查詢中不是其中之一):

  1. 重寫您的代碼,為每個id發出多個並行請求。

  2. 重新訪問您的數據模型,看看您是否有另一個值,通過它來鍵入數據是有意義的。 例如,如果ls所有id碰巧共享一個對它們唯一的公共列值,那么它就是主鍵的一個很好的候選者。 基本上,找到另一種方法來查詢您正在尋找的所有id ,並構建一個特定的查詢表來支持它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM