成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Spark性能調(diào)優(yōu)-RDD算子調(diào)優(yōu)篇

大數(shù)據(jù) 數(shù)據(jù)分析 Spark
Java的序列化機(jī)制使用方便,不需要額外的配置,在算子中使用的變量實(shí)現(xiàn)Serializable接口即可,但是,Java序列化機(jī)制的效率不高,序列化速度慢并且序列化后的數(shù)據(jù)所占用的空間依然較大。

[[385133]]

本文轉(zhuǎn)載自微信公眾號(hào)「五分鐘學(xué)大數(shù)據(jù)」,作者園陌。轉(zhuǎn)載本文請(qǐng)聯(lián)系五分鐘學(xué)大數(shù)據(jù)公眾號(hào)。

Spark調(diào)優(yōu)之RDD算子調(diào)優(yōu)

不廢話,直接進(jìn)入正題!

1. RDD復(fù)用

在對(duì)RDD進(jìn)行算子時(shí),要避免相同的算子和計(jì)算邏輯之下對(duì)RDD進(jìn)行重復(fù)的計(jì)算,如下圖所示:

RDD的重復(fù)計(jì)算

 

對(duì)上圖中的RDD計(jì)算架構(gòu)進(jìn)行修改,得到如下圖所示的優(yōu)化結(jié)果:

RDD架構(gòu)優(yōu)化

 

2. 盡早filter

獲取到初始RDD后,應(yīng)該考慮盡早地過(guò)濾掉不需要的數(shù)據(jù),進(jìn)而減少對(duì)內(nèi)存的占用,從而提升Spark作業(yè)的運(yùn)行效率。

3. 讀取大量小文件-用wholeTextFiles

當(dāng)我們將一個(gè)文本文件讀取為 RDD 時(shí),輸入的每一行都會(huì)成為RDD的一個(gè)元素。

也可以將多個(gè)完整的文本文件一次性讀取為一個(gè)pairRDD,其中鍵是文件名,值是文件內(nèi)容。

  1. val input:RDD[String] = sc.textFile("dir/*.log")  

如果傳遞目錄,則將目錄下的所有文件讀取作為RDD。文件路徑支持通配符。

但是這樣對(duì)于大量的小文件讀取效率并不高,應(yīng)該使用 wholeTextFiles

返回值為RDD[(String, String)],其中Key是文件的名稱,Value是文件的內(nèi)容。

  1. def wholeTextFiles(path: String, minPartitions: Int = defaultMinPartitions): RDD[(String, String)]) 

wholeTextFiles讀取小文件:

  1. val filesRDD: RDD[(String, String)] = 
  2. sc.wholeTextFiles("D:\\data\\files", minPartitions = 3) 
  3. val linesRDD: RDD[String] = filesRDD.flatMap(_._2.split("\\r\\n")) 
  4. val wordsRDD: RDD[String] = linesRDD.flatMap(_.split(" ")) 
  5. wordsRDD.map((_, 1)).reduceByKey(_ + _).collect().foreach(println) 

4. mapPartition和foreachPartition

  • mapPartitions

map(_….) 表示每一個(gè)元素

mapPartitions(_….) 表示每個(gè)分區(qū)的數(shù)據(jù)組成的迭代器

普通的map算子對(duì)RDD中的每一個(gè)元素進(jìn)行操作,而mapPartitions算子對(duì)RDD中每一個(gè)分區(qū)進(jìn)行操作。

如果是普通的map算子,假設(shè)一個(gè)partition有1萬(wàn)條數(shù)據(jù),那么map算子中的function要執(zhí)行1萬(wàn)次,也就是對(duì)每個(gè)元素進(jìn)行操作。

map 算子

 

如果是mapPartition算子,由于一個(gè)task處理一個(gè)RDD的partition,那么一個(gè)task只會(huì)執(zhí)行一次function,function一次接收所有的partition數(shù)據(jù),效率比較高。

mapPartition 算子

 

比如,當(dāng)要把RDD中的所有數(shù)據(jù)通過(guò)JDBC寫入數(shù)據(jù),如果使用map算子,那么需要對(duì)RDD中的每一個(gè)元素都創(chuàng)建一個(gè)數(shù)據(jù)庫(kù)連接,這樣對(duì)資源的消耗很大,如果使用mapPartitions算子,那么針對(duì)一個(gè)分區(qū)的數(shù)據(jù),只需要建立一個(gè)數(shù)據(jù)庫(kù)連接。

mapPartitions算子也存在一些缺點(diǎn):對(duì)于普通的map操作,一次處理一條數(shù)據(jù),如果在處理了2000條數(shù)據(jù)后內(nèi)存不足,那么可以將已經(jīng)處理完的2000條數(shù)據(jù)從內(nèi)存中垃圾回收掉;但是如果使用mapPartitions算子,但數(shù)據(jù)量非常大時(shí),function一次處理一個(gè)分區(qū)的數(shù)據(jù),如果一旦內(nèi)存不足,此時(shí)無(wú)法回收內(nèi)存,就可能會(huì)OOM,即內(nèi)存溢出。

因此,mapPartitions算子適用于數(shù)據(jù)量不是特別大的時(shí)候,此時(shí)使用mapPartitions算子對(duì)性能的提升效果還是不錯(cuò)的。(當(dāng)數(shù)據(jù)量很大的時(shí)候,一旦使用mapPartitions算子,就會(huì)直接OOM)

在項(xiàng)目中,應(yīng)該首先估算一下RDD的數(shù)據(jù)量、每個(gè)partition的數(shù)據(jù)量,以及分配給每個(gè)Executor的內(nèi)存資源,如果資源允許,可以考慮使用mapPartitions算子代替map。

  • foreachPartition

rrd.foreache(_….) 表示每一個(gè)元素

rrd.forPartitions(_….) 表示每個(gè)分區(qū)的數(shù)據(jù)組成的迭代器

在生產(chǎn)環(huán)境中,通常使用foreachPartition算子來(lái)完成數(shù)據(jù)庫(kù)的寫入,通過(guò)foreachPartition算子的特性,可以優(yōu)化寫數(shù)據(jù)庫(kù)的性能。

如果使用foreach算子完成數(shù)據(jù)庫(kù)的操作,由于foreach算子是遍歷RDD的每條數(shù)據(jù),因此,每條數(shù)據(jù)都會(huì)建立一個(gè)數(shù)據(jù)庫(kù)連接,這是對(duì)資源的極大浪費(fèi),因此,對(duì)于寫數(shù)據(jù)庫(kù)操作,我們應(yīng)當(dāng)使用foreachPartition算子。

與mapPartitions算子非常相似,foreachPartition是將RDD的每個(gè)分區(qū)作為遍歷對(duì)象,一次處理一個(gè)分區(qū)的數(shù)據(jù),也就是說(shuō),如果涉及數(shù)據(jù)庫(kù)的相關(guān)操作,一個(gè)分區(qū)的數(shù)據(jù)只需要?jiǎng)?chuàng)建一次數(shù)據(jù)庫(kù)連接,如下圖所示:

foreachPartition 算子

 

使用了foreachPartition 算子后,可以獲得以下的性能提升:

  1. 對(duì)于我們寫的function函數(shù),一次處理一整個(gè)分區(qū)的數(shù)據(jù);
  2. 對(duì)于一個(gè)分區(qū)內(nèi)的數(shù)據(jù),創(chuàng)建唯一的數(shù)據(jù)庫(kù)連接;
  3. 只需要向數(shù)據(jù)庫(kù)發(fā)送一次SQL語(yǔ)句和多組參數(shù);

在生產(chǎn)環(huán)境中,全部都會(huì)使用foreachPartition算子完成數(shù)據(jù)庫(kù)操作。foreachPartition算子存在一個(gè)問(wèn)題,與mapPartitions算子類似,如果一個(gè)分區(qū)的數(shù)據(jù)量特別大,可能會(huì)造成OOM,即內(nèi)存溢出。

5. filter+coalesce/repartition(減少分區(qū))

在Spark任務(wù)中我們經(jīng)常會(huì)使用filter算子完成RDD中數(shù)據(jù)的過(guò)濾,在任務(wù)初始階段,從各個(gè)分區(qū)中加載到的數(shù)據(jù)量是相近的,但是一旦進(jìn)過(guò)filter過(guò)濾后,每個(gè)分區(qū)的數(shù)據(jù)量有可能會(huì)存在較大差異,如下圖所示:

分區(qū)數(shù)據(jù)過(guò)濾結(jié)果

 

根據(jù)上圖我們可以發(fā)現(xiàn)兩個(gè)問(wèn)題:

  1. 每個(gè)partition的數(shù)據(jù)量變小了,如果還按照之前與partition相等的task個(gè)數(shù)去處理當(dāng)前數(shù)據(jù),有點(diǎn)浪費(fèi)task的計(jì)算資源;
  2. 每個(gè)partition的數(shù)據(jù)量不一樣,會(huì)導(dǎo)致后面的每個(gè)task處理每個(gè)partition數(shù)據(jù)的時(shí)候,每個(gè)task要處理的數(shù)據(jù)量不同,這很有可能導(dǎo)致數(shù)據(jù)傾斜問(wèn)題。

如上圖所示,第二個(gè)分區(qū)的數(shù)據(jù)過(guò)濾后只剩100條,而第三個(gè)分區(qū)的數(shù)據(jù)過(guò)濾后剩下800條,在相同的處理邏輯下,第二個(gè)分區(qū)對(duì)應(yīng)的task處理的數(shù)據(jù)量與第三個(gè)分區(qū)對(duì)應(yīng)的task處理的數(shù)據(jù)量差距達(dá)到了8倍,這也會(huì)導(dǎo)致運(yùn)行速度可能存在數(shù)倍的差距,這也就是數(shù)據(jù)傾斜問(wèn)題。

針對(duì)上述的兩個(gè)問(wèn)題,我們分別進(jìn)行分析:

  1. 針對(duì)第一個(gè)問(wèn)題,既然分區(qū)的數(shù)據(jù)量變小了,我們希望可以對(duì)分區(qū)數(shù)據(jù)進(jìn)行重新分配,比如將原來(lái)4個(gè)分區(qū)的數(shù)據(jù)轉(zhuǎn)化到2個(gè)分區(qū)中,這樣只需要用后面的兩個(gè)task進(jìn)行處理即可,避免了資源的浪費(fèi)。
  2. 針對(duì)第二個(gè)問(wèn)題,解決方法和第一個(gè)問(wèn)題的解決方法非常相似,對(duì)分區(qū)數(shù)據(jù)重新分配,讓每個(gè)partition中的數(shù)據(jù)量差不多,這就避免了數(shù)據(jù)傾斜問(wèn)題。

那么具體應(yīng)該如何實(shí)現(xiàn)上面的解決思路?我們需要coalesce算子。

repartition與coalesce都可以用來(lái)進(jìn)行重分區(qū),其中repartition只是coalesce接口中shuffle為true的簡(jiǎn)易實(shí)現(xiàn),coalesce默認(rèn)情況下不進(jìn)行shuffle,但是可以通過(guò)參數(shù)進(jìn)行設(shè)置。

假設(shè)我們希望將原本的分區(qū)個(gè)數(shù)A通過(guò)重新分區(qū)變?yōu)锽,那么有以下幾種情況:

1.A > B(多數(shù)分區(qū)合并為少數(shù)分區(qū))

  • A與B相差值不大

此時(shí)使用coalesce即可,無(wú)需shuffle過(guò)程。

  • A與B相差值很大

此時(shí)可以使用coalesce并且不啟用shuffle過(guò)程,但是會(huì)導(dǎo)致合并過(guò)程性能低下,所以推薦設(shè)置coalesce的第二個(gè)參數(shù)為true,即啟動(dòng)shuffle過(guò)程。

2.A < B(少數(shù)分區(qū)分解為多數(shù)分區(qū))

此時(shí)使用repartition即可,如果使用coalesce需要將shuffle設(shè)置為true,否則coalesce無(wú)效。

我們可以在filter操作之后,使用coalesce算子針對(duì)每個(gè)partition的數(shù)據(jù)量各不相同的情況,壓縮partition的數(shù)量,而且讓每個(gè)partition的數(shù)據(jù)量盡量均勻緊湊,以便于后面的task進(jìn)行計(jì)算操作,在某種程度上能夠在一定程度上提升性能。

注意:local模式是進(jìn)程內(nèi)模擬集群運(yùn)行,已經(jīng)對(duì)并行度和分區(qū)數(shù)量有了一定的內(nèi)部?jī)?yōu)化,因此不用去設(shè)置并行度和分區(qū)數(shù)量。

6. 并行度設(shè)置

Spark作業(yè)中的并行度指各個(gè)stage的task的數(shù)量。

如果并行度設(shè)置不合理而導(dǎo)致并行度過(guò)低,會(huì)導(dǎo)致資源的極大浪費(fèi),例如,20個(gè)Executor,每個(gè)Executor分配3個(gè)CPU core,而Spark作業(yè)有40個(gè)task,這樣每個(gè)Executor分配到的task個(gè)數(shù)是2個(gè),這就使得每個(gè)Executor有一個(gè)CPU core空閑,導(dǎo)致資源的浪費(fèi)。

理想的并行度設(shè)置,應(yīng)該是讓并行度與資源相匹配,簡(jiǎn)單來(lái)說(shuō)就是在資源允許的前提下,并行度要設(shè)置的盡可能大,達(dá)到可以充分利用集群資源。合理的設(shè)置并行度,可以提升整個(gè)Spark作業(yè)的性能和運(yùn)行速度。

Spark官方推薦,task數(shù)量應(yīng)該設(shè)置為Spark作業(yè)總CPU core數(shù)量的2~3倍。之所以沒(méi)有推薦task數(shù)量與CPU core總數(shù)相等,是因?yàn)閠ask的執(zhí)行時(shí)間不同,有的task執(zhí)行速度快而有的task執(zhí)行速度慢,如果task數(shù)量與CPU core總數(shù)相等,那么執(zhí)行快的task執(zhí)行完成后,會(huì)出現(xiàn)CPU core空閑的情況。如果task數(shù)量設(shè)置為CPU core總數(shù)的2~3倍,那么一個(gè)task執(zhí)行完畢后,CPU core會(huì)立刻執(zhí)行下一個(gè)task,降低了資源的浪費(fèi),同時(shí)提升了Spark作業(yè)運(yùn)行的效率。

Spark作業(yè)并行度的設(shè)置如下:

  1. val conf = new SparkConf().set("spark.default.parallelism""500"

原則:讓 cpu 的 core(cpu 核心數(shù)) 充分利用起來(lái), 如有100個(gè) core,那么并行度可以設(shè)置為200~300。

7. repartition/coalesce調(diào)節(jié)并行度

Spark 中雖然可以設(shè)置并行度的調(diào)節(jié)策略,但是,并行度的設(shè)置對(duì)于Spark SQL是不生效的,用戶設(shè)置的并行度只對(duì)于Spark SQL以外的所有Spark的stage生效。

Spark SQL的并行度不允許用戶自己指定,Spark SQL自己會(huì)默認(rèn)根據(jù)hive表對(duì)應(yīng)的HDFS文件的split個(gè)數(shù)自動(dòng)設(shè)置Spark SQL所在的那個(gè)stage的并行度,用戶自己通 spark.default.parallelism 參數(shù)指定的并行度,只會(huì)在沒(méi)Spark SQL的stage中生效。

由于Spark SQL所在stage的并行度無(wú)法手動(dòng)設(shè)置,如果數(shù)據(jù)量較大,并且此stage中后續(xù)的transformation操作有著復(fù)雜的業(yè)務(wù)邏輯,而Spark SQL自動(dòng)設(shè)置的task數(shù)量很少,這就意味著每個(gè)task要處理為數(shù)不少的數(shù)據(jù)量,然后還要執(zhí)行非常復(fù)雜的處理邏輯,這就可能表現(xiàn)為第一個(gè)有Spark SQL的stage速度很慢,而后續(xù)的沒(méi)有Spark SQL的stage運(yùn)行速度非常快。

為了解決Spark SQL無(wú)法設(shè)置并行度和task數(shù)量的問(wèn)題,我們可以使用repartition算子。

repartition 算子使用前后對(duì)比圖如下:

repartition 算子使用前后對(duì)比圖

 

Spark SQL這一步的并行度和task數(shù)量肯定是沒(méi)有辦法去改變了,但是,對(duì)于Spark SQL查詢出來(lái)的RDD,立即使用repartition算子,去重新進(jìn)行分區(qū),這樣可以重新分區(qū)為多個(gè)partition,從repartition之后的RDD操作,由于不再涉及Spark SQL,因此stage的并行度就會(huì)等于你手動(dòng)設(shè)置的值,這樣就避免了Spark SQL所在的stage只能用少量的task去處理大量數(shù)據(jù)并執(zhí)行復(fù)雜的算法邏輯。使用repartition算子的前后對(duì)比如上圖所示。

8. reduceByKey本地預(yù)聚合

reduceByKey相較于普通的shuffle操作一個(gè)顯著的特點(diǎn)就是會(huì)進(jìn)行map端的本地聚合,map端會(huì)先對(duì)本地的數(shù)據(jù)進(jìn)行combine操作,然后將數(shù)據(jù)寫入給下個(gè)stage的每個(gè)task創(chuàng)建的文件中,也就是在map端,對(duì)每一個(gè)key對(duì)應(yīng)的value,執(zhí)行reduceByKey算子函數(shù)。

reduceByKey算子的執(zhí)行過(guò)程如下圖所示:

reduceByKey 算子執(zhí)行過(guò)程

 

使用reduceByKey對(duì)性能的提升如下:

  1. 本地聚合后,在map端的數(shù)據(jù)量變少,減少了磁盤IO,也減少了對(duì)磁盤空間的占用;
  2. 本地聚合后,下一個(gè)stage拉取的數(shù)據(jù)量變少,減少了網(wǎng)絡(luò)傳輸?shù)臄?shù)據(jù)量;
  3. 本地聚合后,在reduce端進(jìn)行數(shù)據(jù)緩存的內(nèi)存占用減少;
  4. 本地聚合后,在reduce端進(jìn)行聚合的數(shù)據(jù)量減少。

基于reduceByKey的本地聚合特征,我們應(yīng)該考慮使用reduceByKey代替其他的shuffle算子,例如groupByKey。

groupByKey與reduceByKey的運(yùn)行原理如下圖1和圖2所示:

圖1:groupByKey原理

圖2:reduceByKey原理

 

根據(jù)上圖可知,groupByKey不會(huì)進(jìn)行map端的聚合,而是將所有map端的數(shù)據(jù)shuffle到reduce端,然后在reduce端進(jìn)行數(shù)據(jù)的聚合操作。由于reduceByKey有map端聚合的特性,使得網(wǎng)絡(luò)傳輸?shù)臄?shù)據(jù)量減小,因此效率要明顯高于groupByKey。

9. 使用持久化+checkpoint

Spark持久化在大部分情況下是沒(méi)有問(wèn)題的,但是有時(shí)數(shù)據(jù)可能會(huì)丟失,如果數(shù)據(jù)一旦丟失,就需要對(duì)丟失的數(shù)據(jù)重新進(jìn)行計(jì)算,計(jì)算完后再緩存和使用,為了避免數(shù)據(jù)的丟失,可以選擇對(duì)這個(gè)RDD進(jìn)行checkpoint,也就是將數(shù)據(jù)持久化一份到容錯(cuò)的文件系統(tǒng)上(比如HDFS)。

一個(gè)RDD緩存并checkpoint后,如果一旦發(fā)現(xiàn)緩存丟失,就會(huì)優(yōu)先查看checkpoint數(shù)據(jù)存不存在,如果有,就會(huì)使用checkpoint數(shù)據(jù),而不用重新計(jì)算。也即是說(shuō),checkpoint可以視為cache的保障機(jī)制,如果cache失敗,就使用checkpoint的數(shù)據(jù)。

使用checkpoint的優(yōu)點(diǎn)在于提高了Spark作業(yè)的可靠性,一旦緩存出現(xiàn)問(wèn)題,不需要重新計(jì)算數(shù)據(jù),缺點(diǎn)在于,checkpoint時(shí)需要將數(shù)據(jù)寫入HDFS等文件系統(tǒng),對(duì)性能的消耗較大。

持久化設(shè)置如下:

  1. sc.setCheckpointDir(‘HDFS’) 
  2. rdd.cache/persist(memory_and_disk) 
  3. rdd.checkpoint 

10. 使用廣播變量

默認(rèn)情況下,task中的算子中如果使用了外部的變量,每個(gè)task都會(huì)獲取一份變量的復(fù)本,這就造成了內(nèi)存的極大消耗。一方面,如果后續(xù)對(duì)RDD進(jìn)行持久化,可能就無(wú)法將RDD數(shù)據(jù)存入內(nèi)存,只能寫入磁盤,磁盤IO將會(huì)嚴(yán)重消耗性能;另一方面,task在創(chuàng)建對(duì)象的時(shí)候,也許會(huì)發(fā)現(xiàn)堆內(nèi)存無(wú)法存放新創(chuàng)建的對(duì)象,這就會(huì)導(dǎo)致頻繁的GC,GC會(huì)導(dǎo)致工作線程停止,進(jìn)而導(dǎo)致Spark暫停工作一段時(shí)間,嚴(yán)重影響Spark性能。

假設(shè)當(dāng)前任務(wù)配置了20個(gè)Executor,指定500個(gè)task,有一個(gè)20M的變量被所有task共用,此時(shí)會(huì)在500個(gè)task中產(chǎn)生500個(gè)副本,耗費(fèi)集群10G的內(nèi)存,如果使用了廣播變量, 那么每個(gè)Executor保存一個(gè)副本,一共消耗400M內(nèi)存,內(nèi)存消耗減少了5倍。

廣播變量在每個(gè)Executor保存一個(gè)副本,此Executor的所有task共用此廣播變量,這讓變量產(chǎn)生的副本數(shù)量大大減少。

在初始階段,廣播變量只在Driver中有一份副本。task在運(yùn)行的時(shí)候,想要使用廣播變量中的數(shù)據(jù),此時(shí)首先會(huì)在自己本地的Executor對(duì)應(yīng)的BlockManager中嘗試獲取變量,如果本地沒(méi)有,BlockManager就會(huì)從Driver或者其他節(jié)點(diǎn)的BlockManager上遠(yuǎn)程拉取變量的復(fù)本,并由本地的BlockManager進(jìn)行管理;之后此Executor的所有task都會(huì)直接從本地的BlockManager中獲取變量。

對(duì)于多個(gè)Task可能會(huì)共用的數(shù)據(jù)可以廣播到每個(gè)Executor上:

  1. val 廣播變量名= sc.broadcast(會(huì)被各個(gè)Task用到的變量,即需要廣播的變量) 
  2.  
  3. 廣播變量名.value//獲取廣播變量 

11. 使用Kryo序列化

默認(rèn)情況下,Spark使用Java的序列化機(jī)制。Java的序列化機(jī)制使用方便,不需要額外的配置,在算子中使用的變量實(shí)現(xiàn)Serializable接口即可,但是,Java序列化機(jī)制的效率不高,序列化速度慢并且序列化后的數(shù)據(jù)所占用的空間依然較大。

Spark官方宣稱Kryo序列化機(jī)制比Java序列化機(jī)制性能提高10倍左右,Spark之所以沒(méi)有默認(rèn)使用Kryo作為序列化類庫(kù),是因?yàn)樗恢С炙袑?duì)象的序列化,同時(shí)Kryo需要用戶在使用前注冊(cè)需要序列化的類型,不夠方便,但從Spark 2.0.0版本開(kāi)始,簡(jiǎn)單類型、簡(jiǎn)單類型數(shù)組、字符串類型的Shuffling RDDs 已經(jīng)默認(rèn)使用Kryo序列化方式了。

Kryo序列化注冊(cè)方式的代碼如下:

  1. public class MyKryoRegistrator implements KryoRegistrator{ 
  2.   @Override 
  3.   public void registerClasses(Kryo kryo){ 
  4.     kryo.register(StartupReportLogs.class); 
  5.   } 

配置Kryo序列化方式的代碼如下:

  1. //創(chuàng)建SparkConf對(duì)象 
  2. val conf = new SparkConf().setMaster(…).setAppName(…) 
  3. //使用Kryo序列化庫(kù) 
  4. conf.set("spark.serializer""org.apache.spark.serializer.KryoSerializer");   
  5. //在Kryo序列化庫(kù)中注冊(cè)自定義的類集合 
  6. conf.set("spark.kryo.registrator""bigdata.com.MyKryoRegistrator");  

 

責(zé)任編輯:武曉燕 來(lái)源: 五分鐘學(xué)大數(shù)據(jù)
相關(guān)推薦

2018-07-18 12:12:20

Spark大數(shù)據(jù)代碼

2017-07-21 08:55:13

TomcatJVM容器

2012-06-20 11:05:47

性能調(diào)優(yōu)攻略

2011-03-10 14:40:54

LAMPMysql

2018-05-28 08:54:45

SparkRDD Cache緩存

2017-07-07 11:01:04

Spark性能調(diào)優(yōu)

2017-10-20 13:41:11

Spark集群代碼

2011-03-18 11:21:48

2016-03-25 09:59:38

性能調(diào)優(yōu)LinuxMySQL

2012-01-10 14:35:08

JavaJVM

2011-05-20 15:02:01

Oracle性能調(diào)優(yōu)

2011-11-14 10:28:23

2020-11-30 11:40:35

NginxLinux性能調(diào)優(yōu)

2021-12-26 00:03:25

Spark性能調(diào)優(yōu)

2011-03-21 09:35:38

LAMP調(diào)優(yōu)網(wǎng)絡(luò)文件

2020-11-09 07:34:49

JVM性能監(jiān)控

2013-02-28 10:15:14

Ubuntu性能調(diào)優(yōu)故障排查

2012-06-21 09:43:45

2024-12-04 15:49:29

2021-11-07 23:49:19

SQL數(shù)據(jù)庫(kù)工具
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 91亚洲精品在线观看 | 久久久天堂 | 国产在线一区二区三区 | 91亚洲欧美| 中文字幕一区二区三区精彩视频 | 日日干干夜夜 | 亚洲一区二区在线视频 | 欧美日韩一二区 | 成年视频在线观看 | 麻豆changesxxx国产 | 欧美久久久久久久久中文字幕 | 国产在线观看一区二区 | 久草热视频 | 男人的天堂一级片 | 久久久女女女女999久久 | 久久成人国产精品 | 夜夜夜夜夜夜曰天天天 | 亚洲精品久| 鸡毛片| 久久久久国产精品www | 一级毛片视频在线观看 | 黄色网址免费看 | av中文字幕网站 | 精品国产一区二区国模嫣然 | 中文字幕在线观看一区 | 成人污污视频 | 成人免费毛片在线观看 | 免费在线观看一区二区 | 精品二区视频 | 天天干天天插 | 中文字字幕一区二区三区四区五区 | 国产美女免费视频 | 黄色一级在线播放 | 日韩免费一区二区 | 亚洲视频在线观看 | 亚洲午夜精品一区二区三区他趣 | 久久久国产一区二区三区 | 午夜免费av | 日本不卡一区 | 午夜精品久久久久久久久久久久久 | 91亚洲视频在线 |