首先感谢来自tidb
徐老师的讲解!此文记录一下看完视频后的读后感。
论文地址:原文
论文备份:百度云 提取码:fxde
视频地址:视频:解读论文《Everything You Always Wanted to Know About Compiled and Vectorized Queries But Were Afraid to Ask》
向量化
What?
首先,什么是向量化?这里主要运用到的是一维的向量,学过线性代数可能知道,一维的向量都是一类的,例如高度、长度、重量。我们可以用一个一维的向量表达多个object的某一个属性,表现到代码里面的就是数组。
Why?
首先要提到两个概念。
- 行存储(row store):处于同一行的数据连续存储;比较有利于整行数据读取的操作。
- 列存储(column store):处于同一列的数据连续存储;比较有利于列数据运算的操作。
为什么需要向量化?在关系型数据库当中,OLTP(Online Transaction Processing)数据库一般是按行存储(row store)的,意思就是同一行数据在存储空间当中是连续的。
下面会举个例子:
在下表中执行:select * from age > 15 and tall < 176
id | name | age | tall |
---|---|---|---|
1 | anker | 25 | 175 |
2 | john | 12 | 165 |
3 | andy | 33 | 178 |
非向量化代码主要是会拿到了同行的其他无用数据,这对于CPU缓存极度不友好,会造成频繁缺页(page)。
非向量化代码(golang)
func where(rows []*Row) []*Row {
var result []*Row
for _, row := range rows {
if row.age > 15 && row.tall < 176 {
result = append(result, row)
}
}
return result
}
向量化代码(golang)
func whereAge(cols []*Col) []int {
selectedCol := make([]int, 0)
for i, colValue := range cols {
if colValue > 15 {
selectedCol = append(selectedCol, i)
}
}
return selectedCol
}
func whereTall(cols []*Col, selected []int) []int {
selectedCol := make([]int, 0)
for _, index := range selected {
if cols[index].tall < 176 {
selectedCol = append(selectedCol, index)
}
}
return selectedCol
}