Apache Doris 是一個基于 MPP 架構(gòu)的高性能、實(shí)時的分析型數(shù)據(jù)庫炕倘,以極速易用的特點(diǎn)被人們所熟知寸谜,僅需亞秒級響應(yīng)時間即可返回海量數(shù)據(jù)下的查詢結(jié)果癌椿,不僅可以支持高并發(fā)的點(diǎn)查詢場景肚菠,也能支持高吞吐的復(fù)雜分析場景舔箭。基于此蚊逢,Apache Doris 能夠較好的滿足報表分析限嫌、即席查詢、統(tǒng)一數(shù)倉構(gòu)建时捌、數(shù)據(jù)湖聯(lián)邦查詢加速等使用場景,用戶可以在此之上構(gòu)建用戶行為分析炉抒、AB 實(shí)驗(yàn)平臺奢讨、日志檢索分析、用戶畫像分析焰薄、訂單分析等應(yīng)用拿诸。
使用 Doris 的用戶都知道 Doris 是完全兼容 MySQL 協(xié)議的,我們可以使用任意 MySQL 客戶端或者 Connector 去連接 Doris塞茅,用 SQL 操作 Doris亩码,這樣你可以使用任意語言來操作 Doris。今天我們演示使用 Go 語言來訪問 Doris 野瘦,完成查詢和 插入操作描沟。
Go 與 MySQL 的結(jié)合還是比較容易的飒泻,像是連接,增吏廉、刪泞遗、改這些操作都比較簡單。
Go 語言的安裝配置還是很簡單的席覆,這里我們就不做介紹了史辙,直接開始
安裝驅(qū)動
安裝 Go 連接 MySQL的驅(qū)動
go get github.com/go-sql-driver/mysql
在我們程序里導(dǎo)入依賴庫
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
連接Doris數(shù)據(jù)庫
var (
// 定義一個全局對象db
db *sql.DB
//連接Doris的用戶名
userName string = "root"
//連接Doris的密碼
password string = ""
//連接Doris的地址
ipAddress string = "127.0.0.1"
//連接Doris的端口號,默認(rèn)是9030
port int = 9030
//連接Doris的具體數(shù)據(jù)庫名稱
dbName string = "test"
)
func initDB() (err error) {
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", userName, password, ipAddress, port, dbName)
//Open打開一個driverName指定的數(shù)據(jù)庫,dataSourceName指定數(shù)據(jù)源
//不會校驗(yàn)用戶名和密碼是否正確佩伤,只會對dsn的格式進(jìn)行檢測
db, err = sql.Open("mysql", dsn)
//dsn格式不正確的時候會報錯
if err != nil {
return err
}
//嘗試與數(shù)據(jù)庫連接聊倔,校驗(yàn)dsn是否正確
err = db.Ping()
if err != nil {
fmt.Println("校驗(yàn)失敗,err", err)
return err
}
// 設(shè)置最大連接數(shù)
db.SetMaxOpenConns(50)
// 設(shè)置最大的空閑連接數(shù)
// db.SetMaxIdleConns(20)
fmt.Println("連接數(shù)據(jù)庫成功!")
return nil
}
驗(yàn)證連接
func main() {
err := initDB()
if err != nil {
fmt.Println("初始化數(shù)據(jù)庫失敗,err", err)
return
}
}
查詢數(shù)據(jù)表
這里我們簡單做一個查詢表里的所有數(shù)據(jù)
我的表結(jié)構(gòu)如下:
CREATE TABLE `t_cn_search` (
`md5` varchar(100) NULL,
`book_line` text NULL,
INDEX idx_line (`book_line`) USING INVERTED PROPERTIES("parser" = "chinese", "support_phrase" = "true") COMMENT ''
) ENGINE=OLAP
DUPLICATE KEY(`md5`)
COMMENT 'OLAP'
DISTRIBUTED BY HASH(`md5`) BUCKETS 2
PROPERTIES (
"replication_allocation" = "tag.location.default: 1",
"is_being_synced" = "false",
"storage_format" = "V2",
"light_schema_change" = "true",
"disable_auto_compaction" = "false",
"enable_single_replica_compaction" = "false"
);
我這個表是一個日志檢索用的表生巡,使用了 Doris 的倒排索引耙蔑,我們匹配任意關(guān)鍵字粒子
查詢程序:
// 查詢數(shù)據(jù)
func QueryRow() {
rows, _ := db.Query("select * from t_cn_search where book_line MATCH_ANY '粒子'") //獲取所有數(shù)據(jù)
var md5 int
var book_line string
for rows.Next() { //循環(huán)顯示所有的數(shù)據(jù)
rows.Scan(&md5, &book_line)
fmt.Println(md5, "--", book_line)
}
}
我們執(zhí)行程序可以看到查詢結(jié)果:
插入數(shù)據(jù)
我們現(xiàn)在來演示怎么插入數(shù)據(jù),這個演示的是我們通過 Doris 提供的 TVF(Table Value Function)將 HDFS 上文件數(shù)據(jù)直接導(dǎo)入到 Doris 的表里障斋。
我的 hdfs 上的文件格式是 Parquet纵潦,我們可以通過 TVF 來看一下這個表的數(shù)據(jù)結(jié)構(gòu)
mysql> desc function hdfs(
-> "uri" = "hdfs://localhost:9000/tmp/test.parquet",
-> "fs.defaultFS" = "hdfs://localhost:9000",
-> "hadoop.username" = "doris",
-> "format" = "parquet");
+----------------+------+------+-------+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------+------+------+-------+---------+-------+
| date | TEXT | Yes | false | NULL | NONE |
| user_src | TEXT | Yes | false | NULL | NONE |
| order_src | TEXT | Yes | false | NULL | NONE |
| order_location | TEXT | Yes | false | NULL | NONE |
| new_order | INT | Yes | false | NULL | NONE |
| payed_order | INT | Yes | false | NULL | NONE |
| pending_order | INT | Yes | false | NULL | NONE |
| cancel_order | INT | Yes | false | NULL | NONE |
| reject_order | INT | Yes | false | NULL | NONE |
| good_order | INT | Yes | false | NULL | NONE |
| report_order | INT | Yes | false | NULL | NONE |
+----------------+------+------+-------+---------+-------+
11 rows in set (0.16 sec)
Doris 的表結(jié)構(gòu)如下:
CREATE TABLE `order_analysis` (
`date` varchar(57) NULL,
`user_src` varchar(27) NULL,
`order_src` varchar(33) NULL,
`order_location` varchar(6) NULL,
`new_order` int(11) NULL,
`payed_order` int(11) NULL,
`pending_order` int(11) NULL,
`cancel_order` int(11) NULL,
`reject_order` int(11) NULL,
`good_order` int(11) NULL,
`report_order` int(11) NULL
) ENGINE=OLAP
DUPLICATE KEY(`date`)
COMMENT 'OLAP'
DISTRIBUTED BY HASH(`date`) BUCKETS 2
PROPERTIES (
"replication_allocation" = "tag.location.default: 1",
"is_being_synced" = "false",
"storage_format" = "V2",
"light_schema_change" = "true",
"disable_auto_compaction" = "false",
"enable_single_replica_compaction" = "false"
);
將 hdfs 文件數(shù)據(jù)導(dǎo)入到 Doris 表里,這里我們使用的是 insert into tbl select
這個操作
func insert() {
result, err := db.Exec("insert into order_analysis select * from hdfs(" +
"\"uri\" = \"hdfs://localhost:9000/tmp/test.parquet\"," +
"\"fs.defaultFS\" = \"hdfs://localhost:9000\"," +
"\"hadoop.username\" = \"doris\"," +
"\"format\" = \"parquet\")")
if err != nil {
fmt.Println("預(yù)處理失敗:", err)
return
}
if err != nil {
fmt.Println("執(zhí)行預(yù)處理失敗:", err)
return
} else {
rows, _ := result.RowsAffected()
fmt.Println("執(zhí)行成功,影響行數(shù)", rows, "行")
}
}
執(zhí)行完成之后我們可以看到返回的結(jié)果
連接數(shù)據(jù)庫成功垃环!
執(zhí)行成功,影響行數(shù) 5061 行
總結(jié)
是不是很簡單邀层,你可以使用任意語言通過 MySQL 協(xié)議來操作 Doris ,后面我們會在講解通過 Go 語言使用 Doris 提供的 Stream load(http協(xié)議)來完成數(shù)據(jù)導(dǎo)入的操作遂庄。