以前记录的一些笔记,有点懒直接copy了
spark:
rdd:
resilient
distributed
dataset
spark由一个sparkContext发启,由各个work节点的执行器执行的并行计算task.
核心是RDD
将数据转换成RDD
1. parallelize, 序列化外来数据,即将外来数据转换成RDD,不提倡使用,因为要将
所有数据放进一台集群内存中
eg:
myfirtrdd = parallelize(["pandas","golang","c","python","numpy","matlib"])
2.一般从文件中读取一个存储字符串的RDD方法
lines = sc.textFile("hdfs://master:9000/data")
lines = sc.textFile("test.txt")
RDD操作: 转换操作和执行操作
转换:
filter: 是过滤的转化操作,生成一个新的RDD,不会改变myfirtadd RDD
ardd = myfirtadd.filter(lambda x: "a" in x)
union: 合并两个RDD
unrdd = ardd.union(ardd1)
map: map将RDD中每个元素处理的结果返回
mrdd = ardd.map(lambda x: x+"bkb")
flatmap:类似map,不同在于 输入一个元素,输出多个元素,
一个例子可以看出区别:
data = sc.parallelize(["hello world", "how are you"])
mapdata = data.map(lambda x: x.split()).collect()
output:
[['hello','world'],['how','are','you']]
flatmapdata = data.flatMap(lambda x: x.split()).collect()
output:
['hello','world', 'how','are','you']
distinct(): 去重, 调用网络进行混洗shuffle,(有方法避免)开销很大。
intersection(rdd): 求交, 调用网络进行混洗shuffle,(有方法避免)开销很大
subtract(rdd): 去除, 调用网络进行混洗shuffle,(有方法避免)开销很大
cartesian(rdd): 乱组,开销巨大
执行:
count: 数据的大小
eg: ardd.count()
countByValue: 返回RDD每个元素的个数
eg: ardd.countByValue()
output:
defaultdict(int, {1: 1, 2: 1, 3: 1, 4: 1, 5: 1, 6: 1, 7: 1, 8: 1})
collect: 获取RDD 所有的数据,调用此函数一定要注意,你的数据量有多大,内存是否够用
eg: ardd.collect()
take: take(n) 获取RDD数据n条
eg: ardd.take(3)
takeOrdered: 返回n条,n条排好顺序的
takeOrdered(n)
top: 返回默认顺序的
num = sc.parallelize([1,2,3,5,6,8])
eg: num.top(2)
return [8,6]
reduce: reduce(func) func参数时RDD中的两个元素返回一个新元素.
eg: data = sc.parallelize([1,2,3,4,5])
data.reduce(lambda x,y: x+y) 返回15
fold: 功能类似reduce只不过它带有初始化值参数
eg: data=flod(1)(lambda x,y: x+y)
aggregate: 这个参数可以返回不同数据类型的值
eg: num = sc.parallelize([1,2,3,4,5])
返回总和,与数量
num.aggragate((0,0), #初始化
(lambda acc,value:(acc[0]+value, acc[1]+1)), #累加
(lambda acc1,acc2:(acc1[0]+acc2[0],acc1[1]+acc2[1]))) #合并累加器
foreach: 有时候我们希望对RDD每个元素处理,但是不返回到驱动器程序中,用foreach(func)
takeSample: 驱动器程序中采样
takeSample(withReplace, num, [seed])
withReplace:true/false 是否有放回采样
num: 采样数据大小
seed: 随机种子
eg:
num = sc.parallelize([1,2,3,4,5])
num.takeSample(false, 1)
1. 综上RDD与RDD之间是有依赖关系的,spark中会使用lineage graph(谱系图)来纪录不同RDD之间的依赖关系.
2.每一次RDD行动操作时,整个RDD都会从头开始计算,需要避免这种低效的行为,用户可以将中间结果持久化.
3. class 编程的时候一定要注意:
class SearchFunc(object):
def __init__(self, query):
self.query = query
def Get(self, rdd):
return rdd.filter(lambda x: self.query in x)
spark会将正常self 序列化发送到work节点上,应该尽量避免,可以这样做
def Get(self, rdd):
query = self.query
return rdd.filter(lambda x: query in x)
4. 不同的RDD类型间的转换
1. mean,variance 只适用数值型RDD
2. join 只能用于键值对RDD
python可以不用去转换
5. 持久化(缓存)
spark是惰性求值,每次执行操作才把RDD都执行一遍,这样每次都执行整个RDD,造成性能下降,所以我们需要将一些RDD保存下来(持久化)
python中调用persist,默认是持久化到JVM堆空间.
键值对操作:
spark 提供一些键值对类型的RDD,并且专门提供了一些操作。
eg: pairs = lines.map(lambda x: (x.split(" "),x))
python中构建键值对RDD,只需要返回二元元组RDD
这其实是一对RDD
Pair RDD转换操作:
reduceByKey(func): func对每个key相同的元素做reduce
groupByKey(): 按照key分组
combineByKey(creater,mergevalue,mergeCombine):
类似与aggragate,使用不同的返回类型合并相同的键值
1. 他会遍历分区中所有的元素
2. 每个元素需要经过 create(创建该键的累加器的初始值),已经存在的需要mergeValue
3. 由于每个分区都是独立处理的,所以需要合并分区中对应键的累加器
eg:
sumCount = pair.combineByKey(
(lambda x: (x,1)),
(lambda x,y:(x[0]+y,x[0]+1),
(lambda x, y: (x[0]+y[0],x[1]+y[1]))
)
pair ([(1, 4), (2, 5), (3, 6), (1, 4), (3, 6)])
sumCount.collectAsMap()
{1: (8, 2), 2: (5, 1), 3: (12, 2)}
4. mapValue(func)对pair RDD中的每个值应用map
eg:
pair.mapValue(lambda x: x*2).collect()
output: [(1, 8), (2, 10), (3, 12), (1, 8), (3, 12)]
5. keys: 返回所有的key
6. values: 返回所有的value
7. sortByKey: 按照key排序
8. subtractByKey(other): 删除other中存在的键值
9. join(other):两个RDD内联
pair ([(1, 4), (2, 5), (3, 6), (1, 4), (3, 6)])
other ([(1, 8), (2, 10), (3, 12), (1, 8), (3, 12)])
pair.join(other)
output:
[
(1,(4,8)),
(1,(4,8)),
(1,(4,8)),
(1,(4,8)),
(2,(5,10)),
(3,(6,12)),
(3,(6,12)),
(3,(6,12)),
(3,(6,12))
]
10. rightOuterJoin 右连
11. leftOuterJoin 左连
12. cogroup 类似交叉连
)
行动操作:
countByKey:统计每个key的数量
collectAsMap: python中以字典的形式,但是相同的key只会显示一个值
lookup(key): 返回key的值
数据分区:
为了提供性能,减少网络开销,回对数据经行分区,
比如,键值对的聚合操作,就希望,每一种key的数据在一个分区中,可以调用
转换操作: partitionBy(100),建立100个哈希分区
也可以自定义分区:
import urlparse
def hash_domain(url):
return hash(urlparse.urlparse(url).netloc)
rdd.partitionBy(20, hash_domain)
读取数据与保存数据:
文本文件:
文件读取:
textFile(path) path也可以是目录,也支持通配符,如 part*.txt
wholeTextFiles(path)返回 一个pair RDD,key 是文件名
保存文件:
saveAsTextFile(path)
JSON文件:
读取:
import json
data = input.map(lambda x: json.loads(x))
保存文件:
(data.filter(lambda a: a["love"]).map(lambda x: json.load(x))).saveAsTextFile(/mydata)
CSV文件:
解析:
def load(line):
#解析一行纪录
input = StringIO.StringIO(line)
reader = csv.DictReader(input, fieldnames=["name", "Animal"])
return reader.next()
input = sc.textFile(inputFile).map(load)
def loadRecords(fileNameContents):
#解析文件中所有的纪录
input = StringIO.StringIO(fileNameContents[1])
reader = csv.DictReader(input, fieldnames=["name", "Animal"])
return reader
fullfiledata = sc.wholeTextFiles(inputFile).map(loadRecords)
CSV保存:
def writeRecords(records):
output = StringIO.StringIO()
writer = csv.DictWriter(output, fieldnames=["name","Animal"])
for recore in records:
writer.writerow(recore)
return [output.getvalue()]
pandasdata.mapPartitions(writeRecords).saveAsTextFile('/myoutput')
sequenceFile文件:
读取:
data = sc.sequenceFile(inFile, "org.apache.hadoop.io.Text", "org.apache.hadoop.io.InWritable")
保存:
data.saveAsSequenceFile(outputFile)
HDFS文件:
类似与文本文件
结构化数据hive:
from pyspark.sql import HiveContext
hiveCtx = HiveContext(sc)
rows = hiveCtx.sql(sql)
firstRow = rows.first()
tweets = hiveCtx.jsonFile("t.json")
tweets.registerTemTable("tweets") 系那个t.json数据注册为一张表
result = hiveCtx.sql("select user.name, text from tweets")查询这张表
连接到Hbase,elasticsearch.