国产秋霞理论久久久电影-婷婷色九月综合激情丁香-欧美在线观看乱妇视频-精品国avA久久久久久久-国产乱码精品一区二区三区亚洲人-欧美熟妇一区二区三区蜜桃视频

騰訊阿里頭條翻牌子 | ClickHouse中SQL執(zhí)行過程

共 15781字,需瀏覽 32分鐘

 ·

2021-03-01 00:11

點(diǎn)擊上方藍(lán)色字體,選擇“設(shè)為星標(biāo)

回復(fù)”資源“獲取更多資源

在上一篇文章中《ClickHouse表引擎到底怎么選》,我們提到了ClickHouse的引擎選擇問題,本文中我們會(huì)介紹在ClickHouse中的SQL執(zhí)行過程。

用戶提交一條查詢SQL背后發(fā)生了什么?

在傳統(tǒng)關(guān)系型數(shù)據(jù)庫中,SQL處理器的組件主要包括以下幾種:
Query Parsing
負(fù)責(zé)進(jìn)行詞法和語法分析,把程序從人類高可讀的格式(即SQL)轉(zhuǎn)化成機(jī)器高可讀的格式(AST,抽象語法樹)。
詞法分析指的是把SQL中的字符序列分解成一個(gè)個(gè)獨(dú)立的詞法單元——Token(<類型,值>)。語法分析指的是從詞法分析器輸出的token中識(shí)別各類短語,并構(gòu)造出一顆抽象語法樹。而按照構(gòu)造抽象語法樹的方向,又可以把語法分析分成自頂向下和自底向上分析兩種。而ClickHouse采用的則是手寫一個(gè)遞歸下降的語法分析器。
Query Rewrite
即通常我們說的"Logical Optimizer"或基于規(guī)則的優(yōu)化器(Rule-Based Optimizer,即RBO)。
其負(fù)責(zé)應(yīng)用一些啟發(fā)式規(guī)則,負(fù)責(zé)簡化和標(biāo)準(zhǔn)化查詢,無需改變查詢的語義。
常見操作有:謂詞和算子下推,視圖展開,簡化常量運(yùn)算表達(dá)式,謂詞邏輯的重寫,語義的優(yōu)化等。
Query Optimizer
即通常我們所說的"Physical Optimizer",負(fù)責(zé)把內(nèi)部查詢表達(dá)轉(zhuǎn)化成一個(gè)高效的查詢計(jì)劃,指導(dǎo)DBMS如何去取表,如何進(jìn)行排序,如何Join。如下圖所示,一個(gè)查詢計(jì)劃可以被認(rèn)為是一個(gè)數(shù)據(jù)流圖,在這個(gè)數(shù)據(jù)流圖中,表數(shù)據(jù)會(huì)像在管道中傳輸一樣,從一個(gè)查詢操作符(operator)傳遞到另一個(gè)查詢操作符。

Query Executor
查詢執(zhí)行器,負(fù)責(zé)執(zhí)行具體的查詢計(jì)劃,從存儲(chǔ)引擎中獲取數(shù)據(jù)并且對(duì)數(shù)據(jù)應(yīng)用查詢計(jì)劃得到結(jié)果。執(zhí)行引擎也分為很多種,如經(jīng)典的火山模型(Volcano Model),還有ClickHouse采用的向量化執(zhí)行模型(Vectorization Model)。

但不管是傳統(tǒng)的關(guān)系型數(shù)據(jù)庫,還是非關(guān)系型數(shù)據(jù)庫,SQL的解析和生成執(zhí)行計(jì)劃過程都是大同小異的,而縱覽ClickHouse的源代碼,可以把用戶提交一條查詢SQL背后的過程總結(jié)如下:
1.服務(wù)端接收客戶端發(fā)來的SQL請(qǐng)求,具體形式是一個(gè)網(wǎng)絡(luò)包,Server的協(xié)議層需要拆包把SQL解析出來
2.Server負(fù)責(zé)初始化上下文與Network Handler,然后 Parser 對(duì)Query做詞法和語法分析,解析成AST
3.Interpreter的 SyntaxAnalyzer 會(huì)應(yīng)用一些啟發(fā)式規(guī)則對(duì)AST進(jìn)行優(yōu)化重寫
4.Interpreter的 ExpressionAnalyzer 根據(jù)上下文信息以及優(yōu)化重寫后的AST生成物理執(zhí)行計(jì)劃
5.物理執(zhí)行計(jì)劃分發(fā)到本地或者分布式的executor,各自從存儲(chǔ)引擎中獲取數(shù)據(jù),應(yīng)用執(zhí)行計(jì)劃
6.Server把執(zhí)行后的結(jié)果以Block流的形式輸出到Socket緩沖區(qū),Client從Socket中讀取即可得到結(jié)果

接收客戶端請(qǐng)求

我們要以服務(wù)端的視角來出發(fā),首先來看server.cpp大概做什么事情:
下面只挑選重要的邏輯:
  • 初始化上下文

  • 初始化Zookeeper(ClickHouse的副本復(fù)制機(jī)制需要依賴ZooKeeper)

  • 常規(guī)配置初始化

  • 綁定服務(wù)端的端口,根據(jù)網(wǎng)絡(luò)協(xié)議初始化Handler,對(duì)客戶端提供服務(wù)

int Server::main()
{
// 初始化上下文
global_context = std::make_unique<Context>(Context::createGlobal());
global_context->setApplicationType(Context::ApplicationType::SERVER);

// zk初始化
zkutil::ZooKeeperNodeCache main_config_zk_node_cache([&] { return global_context->getZooKeeper(); });

//其他config的初始化
//...

//綁定端口,對(duì)外提供服務(wù)
auto address = make_socket_address(host, port);
socket.bind(address, /* reuseAddress = */ true);

//根據(jù)網(wǎng)絡(luò)協(xié)議建立不同的server類型
//現(xiàn)在支持的server類型有:HTTP,HTTPS,TCP,Interserver,mysql
//以TCP版本為例:
create_server("tcp_port", [&](UInt16 port)
{
Poco::Net::ServerSocket socket;
auto address = socket_bind_listen(socket, listen_host, port);
servers.emplace_back(std::make_unique<Poco::Net::TCPServer>(
new TCPHandlerFactory(*this),
server_pool,
socket,
new Poco::Net::TCPServerParams));
});

//啟動(dòng)server
for (auto & server : servers)
server->start();

}
客戶端發(fā)來的請(qǐng)求是由各自網(wǎng)絡(luò)協(xié)議所對(duì)應(yīng)的 Handler 來進(jìn)行的,server在啟動(dòng)的時(shí)候 Handler 會(huì)被初始化并綁定在指定端口中。我們以TCPHandler為例,看看服務(wù)端是如何處理客戶端發(fā)來的請(qǐng)求的,重點(diǎn)關(guān)注 TCPHandler::runImpl 的函數(shù)實(shí)現(xiàn):
  • 初始化輸入和輸出流的緩沖區(qū)

  • 接受請(qǐng)求報(bào)文,拆包

  • 執(zhí)行Query(包括整個(gè)詞法語法分析,Query重寫,物理計(jì)劃生成和生成結(jié)果)

  • 把Query結(jié)果保存到輸出流,然后發(fā)送到Socket的緩沖區(qū),等待發(fā)送回客戶端

void TCPHandler::runImpl()
{
//實(shí)例化套接字對(duì)應(yīng)的輸入和輸出流緩沖區(qū)
in = std::make_shared<ReadBufferFromPocoSocket>(socket());
out = std::make_shared<WriteBufferFromPocoSocket>(socket());

while (1){
// 接收請(qǐng)求報(bào)文
receivePacket();

// 執(zhí)行Query
state.io = executeQuery(state.query, *query_context, false, state.stage, may_have_embedded_data);

//根據(jù)Query種類來處理不同的Query
//處理insert Query
processInsertQuery();
//并發(fā)處理普通Query
processOrdinaryQueryWithProcessors();
//單線程處理普通Query
processOrdinaryQuery();
}
}
那CK處理客戶端發(fā)送過來的Query的具體邏輯是怎樣的呢?我們可以在dbms/src/Interpreters/executeQuery.cpp 中一探究竟。具體邏輯在 executeQueryImpl 函數(shù)中,挑選核心的邏輯進(jìn)行講解:
static std::tuple<ASTPtr, BlockIO> executeQueryImpl()
{
//構(gòu)造Parser
ParserQuery parser(end, settings.enable_debug_queries);
ASTPtr ast;

//把Query轉(zhuǎn)化為抽象語法樹
ast = parseQuery(parser, begin, end, "", max_query_size);

//生成interpreter實(shí)例
auto interpreter = InterpreterFactory::get(ast, context, stage);

// interpreter解析AST,結(jié)果是BlockIO
res = interpreter->execute();

//返回結(jié)果是抽象語法樹和解析后的結(jié)果組成的二元組
return std::make_tuple(ast, res);
}
該函數(shù)所做的事情:
  • 構(gòu)建Parser,把Query解析成AST(抽象語法樹)

  • InterpreterFactory根據(jù)AST生成對(duì)應(yīng)的Interpreter實(shí)例

  • AST是由Interpreter來解析的,執(zhí)行結(jié)果是一個(gè)BlockIO,BlockIO是對(duì) BlockInputStream 和 BlockOutputStream 的一個(gè)封裝。

總結(jié):
  • 服務(wù)端調(diào)用 executeQuery 來處理client發(fā)送的Query,執(zhí)行后的結(jié)果保存在state這個(gè)結(jié)構(gòu)體的io成員中。

  • 每一條Query都會(huì)對(duì)應(yīng)一個(gè)state結(jié)構(gòu)體,記錄了這條Query的id,處理狀態(tài),壓縮算法,Query的文本和Query所處理數(shù)據(jù)對(duì)應(yīng)的IO流等元信息。

  • 然后服務(wù)端調(diào)用 processOrdinaryQuery 等方法把輸出流結(jié)果封裝成異步的IO流,發(fā)送到回client。

解析請(qǐng)求(Parser)

CK選擇采用手寫一個(gè)遞歸下降的Parser來對(duì)SQL進(jìn)行解析,生成的結(jié)果是這個(gè)SQL對(duì)應(yīng)的抽象語法樹(AST),抽象語法樹由表示各個(gè)操作的節(jié)點(diǎn)(IAST)表示。而本節(jié)主要介紹Parser背后的核心邏輯:
  1. 詞法分析和語法分析的核心邏輯可以在parseQuery.cpp的 tryParseQuery 中一覽無余。

  2. 該函數(shù)利用lexer將掃描Query字符流,將其分割為一個(gè)個(gè)的Token, token_iterator 即一個(gè)Token流迭代器,然后parser再對(duì)Token流進(jìn)行解析生成AST抽象語法樹。

ASTPtr tryParseQuery()
{
//Token為lexer詞法分析后的基本單位,詞法分析后生成的是Token流
Tokens tokens(pos, end, max_query_size);
IParser::Pos token_iterator(tokens);
ASTPtr res;
//Token流經(jīng)過語法分析生成AST抽象語法樹
bool parse_res = parser.parse(token_iterator, res, expected);
return res;

}
我們可以看到,語法分析的核心就在于parser執(zhí)行的parse方法。parse 方法具體的實(shí)現(xiàn)在 ParserQuery.cpp 的 parseImpl 中。
bool ParserQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{
ParserQueryWithOutput query_with_output_p(enable_explain);
ParserInsertQuery insert_p(end);
ParserUseQuery use_p;
ParserSetQuery set_p;
ParserSystemQuery system_p;

bool res = query_with_output_p.parse(pos, node, expected)
|| insert_p.parse(pos, node, expected)
|| use_p.parse(pos, node, expected)
|| set_p.parse(pos, node, expected)
|| system_p.parse(pos, node, expected);

return res;
}
我們可以看到,這個(gè)方法粗略地把Query分為了五種,但是本質(zhì)上可以歸納為兩種(第一種為有結(jié)果輸出,對(duì)應(yīng)show,select,create等語句;第二種為無結(jié)果輸出,對(duì)應(yīng)insert,use,set和與系統(tǒng)相關(guān)的語句(如exit))
? QueryWithOutput ? InsertQuery ? UseQuery ? SetQuery ? SystemQuery
每一種Query都自定義了其專屬的Parser,所以代碼邏輯是當(dāng)接收到一個(gè)Query輸入的時(shí)候,會(huì)嘗試各種Query的Parser,直到成功為止。
我們可以select語句對(duì)應(yīng)的parser進(jìn)行分析:
核心邏輯可以總結(jié)為:
1.先給出select語句中可能出現(xiàn)的關(guān)鍵詞
2.在詞法分析生成的Token流中爬取這些關(guān)鍵詞
3.如果成功爬取,則 setExpression 函數(shù)會(huì)組裝該關(guān)鍵字對(duì)應(yīng)的AST節(jié)點(diǎn)
每一種SQL語句(如select,drop,insert,create)都有對(duì)應(yīng)的AST類,并且分別包含了這些語句中特有的關(guān)鍵字。
bool ParserSelectQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{
//創(chuàng)建AST樹節(jié)點(diǎn)
auto select_query = std::make_shared<ASTSelectQuery>();
node = select_query;

//select語句中會(huì)出現(xiàn)的關(guān)鍵詞
ParserKeyword s_select("SELECT");
ParserKeyword s_distinct("DISTINCT");
ParserKeyword s_from("FROM");
ParserKeyword s_prewhere("PREWHERE");
ParserKeyword s_where("WHERE");
ParserKeyword s_group_by("GROUP BY");
ParserKeyword s_with("WITH");
ParserKeyword s_totals("TOTALS");
ParserKeyword s_having("HAVING");
ParserKeyword s_order_by("ORDER BY");
ParserKeyword s_limit("LIMIT");
ParserKeyword s_settings("SETTINGS");
ParserKeyword s_by("BY");
ParserKeyword s_rollup("ROLLUP");
ParserKeyword s_cube("CUBE");
ParserKeyword s_top("TOP");
ParserKeyword s_with_ties("WITH TIES");
ParserKeyword s_offset("OFFSET");

//...
//依次對(duì)Token流爬取上述關(guān)鍵字
ParserTablesInSelectQuery().parse(pos, tables, expected)

//根據(jù)語法分析結(jié)果設(shè)置AST的Expression屬性,可以理解為如果SQL存在該關(guān)鍵字,這個(gè)關(guān)鍵字都會(huì)轉(zhuǎn)化為AST上的一個(gè)節(jié)點(diǎn)
select_query->setExpression(ASTSelectQuery::Expression::WITH, std::move(with_expression_list));
select_query->setExpression(ASTSelectQuery::Expression::SELECT, std::move(select_expression_list));
select_query->setExpression(ASTSelectQuery::Expression::TABLES, std::move(tables));
select_query->setExpression(ASTSelectQuery::Expression::PREWHERE, std::move(prewhere_expression));
select_query->setExpression(ASTSelectQuery::Expression::WHERE, std::move(where_expression));
select_query->setExpression(ASTSelectQuery::Expression::GROUP_BY, std::move(group_expression_list));
select_query->setExpression(ASTSelectQuery::Expression::HAVING, std::move(having_expression));
select_query->setExpression(ASTSelectQuery::Expression::ORDER_BY, std::move(order_expression_list));
select_query->setExpression(ASTSelectQuery::Expression::LIMIT_BY_OFFSET, std::move(limit_by_offset));
select_query->setExpression(ASTSelectQuery::Expression::LIMIT_BY_LENGTH, std::move(limit_by_length));
select_query->setExpression(ASTSelectQuery::Expression::LIMIT_BY, std::move(limit_by_expression_list));
select_query->setExpression(ASTSelectQuery::Expression::LIMIT_OFFSET, std::move(limit_offset));
select_query->setExpression(ASTSelectQuery::Expression::LIMIT_LENGTH, std::move(limit_length));
select_query->setExpression(ASTSelectQuery::Expression::SETTINGS, std::move(settings));

}
整個(gè)Parser的流程圖:

執(zhí)行請(qǐng)求(Interpreter)

解釋器(Interpreter)負(fù)責(zé)從抽象語法樹中創(chuàng)建查詢執(zhí)行的流水線,整條流水線以 BlockInputStream 和 BlockOutputStream 進(jìn)行組織。比方說"select"是基于"from"的Block輸出流來進(jìn)行選擇的,選擇后的結(jié)果也會(huì)以Block輸出流的形式輸出到結(jié)果。首先我們來看:
dbms/src/Interpreters/InterpreterFactory.cpp
每一種Query都會(huì)有對(duì)應(yīng)的Interpreter,這個(gè)工廠方法就是根據(jù)AST的種類來實(shí)例化其對(duì)應(yīng)的Interpreter,由其來具體執(zhí)行對(duì)應(yīng)AST的執(zhí)行計(jì)劃:
std::unique_ptr<IInterpreter> InterpreterFactory::get(ASTPtr & query, Context & context, QueryProcessingStage::Enum stage)
{
//舉個(gè)例子,如果該AST是由select語句轉(zhuǎn)化過來,
if (query->as<ASTSelectQuery>())
{
/// This is internal part of ASTSelectWithUnionQuery.
/// Even if there is SELECT without union, it is represented by ASTSelectWithUnionQuery with single ASTSelectQuery as a child.
return std::make_unique<InterpreterSelectQuery>(query, context, SelectQueryOptions(stage));
}
}
我們就以 InterpreterSelectQuery 為例,了解其實(shí)例化的核心邏輯:
InterpreterSelectQuery::InterpreterSelectQuery()
{
//獲取AST
auto & query = getSelectQuery();

//對(duì)AST做進(jìn)一步語法分析,對(duì)語法樹做優(yōu)化重寫
syntax_analyzer_result = SyntaxAnalyzer(context, options).analyze(
query_ptr, source_header.getNamesAndTypesList(), required_result_column_names, storage, NamesAndTypesList());

//每一種Query都會(huì)對(duì)應(yīng)一個(gè)特有的表達(dá)式分析器,用于爬取AST生成執(zhí)行計(jì)劃(操作鏈)
query_analyzer = std::make_unique<SelectQueryExpressionAnalyzer>(
query_ptr, syntax_analyzer_result, context,
NameSet(required_result_column_names.begin(), required_result_column_names.end()),
options.subquery_depth, !options.only_analyze);
}
語法分析直接生成的AST轉(zhuǎn)化成執(zhí)行計(jì)劃可能性能上并不是最優(yōu)的,因此需要SyntaxAnalyzer 對(duì)其進(jìn)行優(yōu)化重寫,在其源碼中可以看到其涉及到非常多 基規(guī)則優(yōu)化(rule based optimization) 的trick。SyntaxAnalyzer 會(huì)逐個(gè)針對(duì)這些規(guī)則對(duì)查詢進(jìn)行檢查,確定其是否滿足轉(zhuǎn)換規(guī)則,一旦滿足就會(huì)對(duì)其進(jìn)行轉(zhuǎn)換。
SyntaxAnalyzerResultPtr SyntaxAnalyzer::analyze()
{
// 剔除冗余列
removeDuplicateColumns(result.source_columns);

// 根據(jù)settings中enable_optimize_predicate_expression配置判斷是否進(jìn)行謂詞下移
replaceJoinedTable(node);

// 根據(jù)settings中distributed_product_mode配置重寫IN 與 JOIN 表達(dá)式
InJoinSubqueriesPreprocessor(context).visit(query);

// 優(yōu)化Query內(nèi)部的布爾表達(dá)式
LogicalExpressionsOptimizer().perform();

// 創(chuàng)建一個(gè)從別名到AST節(jié)點(diǎn)的映射字典
QueryAliasesVisitor(query_aliases_data, log.stream()).visit(query);

// 公共子表達(dá)式的消除
QueryNormalizer(normalizer_data).visit(query);

// 消除select從句后的冗余列
removeUnneededColumnsFromSelectClause(select_query, required_result_columns, remove_duplicates);

// 執(zhí)行標(biāo)量子查詢,并且用常量替代標(biāo)量子查詢結(jié)果
executeScalarSubqueries(query, context, subquery_depth);

// 如果是select語句還會(huì)做下列優(yōu)化:

// 謂詞下移優(yōu)化
PredicateExpressionsOptimizer(select_query, settings, context).optimize();

/// GROUP BY 從句的優(yōu)化
optimizeGroupBy(select_query, source_columns_set, context);

/// ORDER BY 從句的冗余項(xiàng)剔除
optimizeOrderBy(select_query);

/// LIMIT BY 從句的冗余列剔除
optimizeLimitBy(select_query);

/// USING語句的冗余列剔除
optimizeUsing(select_query);

}
這里挑選幾個(gè)簡單介紹一下:
公共子表達(dá)式消除(Common Subexpression Elimination)
如果表達(dá)式 x op y 先前被計(jì)算過,并且從先前的計(jì)算到現(xiàn)在其計(jì)算表達(dá)式對(duì)應(yīng)的值沒有改變,那么 x op y 就稱為公共子表達(dá)式。公共子表達(dá)式消除會(huì)搜索所有相同計(jì)算表達(dá)式的實(shí)例,并分析是否值得用保存計(jì)算值的單個(gè)變量來替換它們,以減少計(jì)算的開銷。
標(biāo)量子查詢(Scala Subquery)的常量替換
標(biāo)量子查詢就是返回單一值的子查詢,和公共子表達(dá)式消除相似,可以用常量來替換SQL中所有的標(biāo)量子查詢結(jié)果以減少計(jì)算開銷。
謂詞下移(Predicate Pushdown)
把外層查詢塊中的WHERE子句的謂詞下移到較低層查詢塊如視圖,以盡可能把過濾數(shù)據(jù)的操作移動(dòng)到靠近數(shù)據(jù)源的位置。提前進(jìn)行數(shù)據(jù)過濾能夠大幅減少網(wǎng)絡(luò)傳輸或者內(nèi)存讀取訪問的數(shù)據(jù)量,以提高查詢效率。
而 query_analyzer 的作用可以理解為解析優(yōu)化重寫后的AST,然后對(duì)所要進(jìn)行的操作組成一條操作鏈,即物理執(zhí)行計(jì)劃,如:
ExpressionActionsChain chain;
analyzer.appendWhere(chain);
chain.addStep();
analyzer.appendSelect(chain);
analyzer.appendOrderBy(chain);
chain.finalize();
上述代碼把where,select,orderby操作都加入到操作鏈中,接下來就可以從Storage層讀取Block,對(duì)Block數(shù)據(jù)應(yīng)用上述操作鏈的操作。而執(zhí)行的核心邏輯,就在對(duì)應(yīng)Interpreter的 executeImpl 方法實(shí)現(xiàn)中,這里以select語句的Interpreter來了解下讀取Block數(shù)據(jù)并且對(duì)block數(shù)據(jù)進(jìn)行相應(yīng)操作的流程。
void InterpreterSelectQuery::executeImpl(TPipeline & pipeline, const BlockInputStreamPtr & prepared_input)
{
// 對(duì)應(yīng)Query的AST
auto & query = getSelectQuery();

AnalysisResult expressions;
// 物理計(jì)劃,判斷表達(dá)式是否有where,aggregate,having,order_by,litmit_by等字段
expressions = analyzeExpressions(
getSelectQuery(),
*query_analyzer,
QueryProcessingStage::FetchColumns,
options.to_stage,
context,
storage,
true,
filter_info);

// 從Storage讀取數(shù)據(jù)
executeFetchColumns(from_stage, pipeline, sorting_info, expressions.prewhere_info, expressions.columns_to_remove_after_prewhere);

// eg:根據(jù)SQL的關(guān)鍵字在BlockStream流水線中執(zhí)行相應(yīng)的操作, 如where,aggregate,distinct都分別由一個(gè)函數(shù)負(fù)責(zé)執(zhí)行
executeWhere(pipeline, expressions.before_where, expressions.remove_where_filter);

executeAggregation(pipeline, expressions.before_aggregation, aggregate_overflow_row, aggregate_final);

executeDistinct(pipeline, true, expressions.selected_columns);

}
既然我們知道了執(zhí)行計(jì)劃AnalysisResult(即物理執(zhí)行計(jì)劃),接下來就需要從storage層中讀取數(shù)據(jù)來執(zhí)行對(duì)應(yīng)的操作,核心邏輯在 executeFetchColumns 中: 核心操作就是從storage層讀取所要處理列的Block,并組織成BlockStream。
void InterpreterSelectQuery::executeFetchColumns(
QueryProcessingStage::Enum processing_stage, TPipeline & pipeline,
const SortingInfoPtr & sorting_info, const PrewhereInfoPtr & prewhere_info, const Names & columns_to_remove_after_prewhere)
{
// 實(shí)例化Block Stream
auto streams = storage->read(required_columns, query_info, context, processing_stage, max_block_size, max_streams)
// 讀取列對(duì)應(yīng)的Block,并且組織成Block Stream
streams = {std::make_shared<NullBlockInputStream>(storage->getSampleBlockForColumns(required_columns))};
streams.back() = std::make_shared<ExpressionBlockInputStream>(streams.back(), query_info.prewhere_info->remove_columns_actions);
}
讀取完Block Stream之后就是對(duì)其執(zhí)行各種execute操作如 executeAggregation , executeWhere 操作,詳見 InterpreterSelectQuery::executeImpl 的代碼。
因此Interpreter的處理過程可以總結(jié)為:
? 對(duì)AST進(jìn)行優(yōu)化重寫 ? 解析重寫后的AST并生成操作鏈(執(zhí)行計(jì)劃) ? 從存儲(chǔ)引擎中讀取要處理的Block數(shù)據(jù) ? 對(duì)讀取的Block數(shù)據(jù)應(yīng)用操作鏈上的操作
那我們讀取Block Stream并進(jìn)行處理后,生成的結(jié)果如何寫回到storage層呢? 我們這里以insert語句的Interpreter來了解下:
BlockIO InterpreterInsertQuery::execute()
{
// table為存儲(chǔ)引擎接口
StoragePtr table = getTable(query);
BlockOutputStreamPtr out;

// 從存儲(chǔ)引擎讀取Block Stream
auto query_sample_block = getSampleBlock(query, table);
out = std::make_shared<AddingDefaultBlockOutputStream>(
out, query_sample_block, out->getHeader(), table->getColumns().getDefaults(), context);

//執(zhí)行結(jié)果封裝成BlockIO
BlockIO res;
res.out = std::move(out);
}
上面代碼中的StoragePtr實(shí)際上就是IStorage這個(gè)存儲(chǔ)引擎的接口
using StoragePtr = std::shared_ptr< IStorage>;
無論是寫入還是讀取操作都是依靠底層存儲(chǔ)引擎(如MergeTree)的write和read接口來實(shí)現(xiàn)的,關(guān)于存儲(chǔ)引擎的細(xì)節(jié)實(shí)現(xiàn)這里暫時(shí)不贅述,這里我們只需要知道我們從存儲(chǔ)引擎接口中以流方式讀取Block數(shù)據(jù),而結(jié)果組織成BlockIO流輸出。Interpreter的流程總結(jié)如下:

返回請(qǐng)求結(jié)果 TCPHandler::runImpl 中,執(zhí)行完 executeQuery 之后需要調(diào)用各種processQuery的方法來給client返回執(zhí)行SQL后的結(jié)果。我們以 TCPHandler::processOrdinaryQuery 為例做簡單分析:
void TCPHandler::processOrdinaryQuery() { //把BlockStream封裝成異步的Stream,那么從流中讀取數(shù)據(jù)將會(huì)是異步操作 AsynchronousBlockInputStream async_in(state.io.in);
while(true){
Block block;
//從IO流讀取block數(shù)據(jù)
block = async_in.read();
//發(fā)送block數(shù)據(jù)
sendData(block);
}
} Server負(fù)責(zé)在 sendData 函數(shù)中把輸出結(jié)果寫入到套接字輸出緩沖區(qū)中,client只要從這個(gè)輸出緩沖區(qū)讀取就能夠得到結(jié)果。
void TCPHandler::sendData(const Block & block)
{
//初始化OutputStream的參數(shù)
initBlockOutput(block);

// 調(diào)用BlockOutputStream的write函數(shù),把Block寫到輸出流
state.block_out->write(block);
state.maybe_compressed_out->next();
out->next();
}

結(jié)語

了解ClickHouse背后SQL的查詢整個(gè)流程,不僅能讓數(shù)據(jù)庫使用者更清晰地認(rèn)識(shí)到如何編寫最優(yōu)化的SQL,也能夠讓數(shù)據(jù)庫內(nèi)核開發(fā)者加深對(duì)數(shù)據(jù)庫體系結(jié)構(gòu)的理解,提高開發(fā)效率。


騰訊阿里頭條翻牌子|ClickHouse表引擎到底怎么選

Uber大型實(shí)時(shí)數(shù)據(jù)智能平臺(tái)建設(shè)

物聯(lián)網(wǎng)時(shí)代的答案 - Apache IoTDB

一線互聯(lián)網(wǎng)公司面試進(jìn)階全攻略



歡迎點(diǎn)贊+收藏+轉(zhuǎn)發(fā)朋友圈素質(zhì)三連

文章不錯(cuò)?點(diǎn)個(gè)【在看】吧! 
瀏覽 142
點(diǎn)贊
評(píng)論
收藏
分享

手機(jī)掃一掃分享

分享
舉報(bào)
評(píng)論
圖片
表情
推薦
點(diǎn)贊
評(píng)論
收藏
分享

手機(jī)掃一掃分享

分享
舉報(bào)

感谢您访问我们的网站,您可能还对以下资源感兴趣:

国产秋霞理论久久久电影-婷婷色九月综合激情丁香-欧美在线观看乱妇视频-精品国avA久久久久久久-国产乱码精品一区二区三区亚洲人-欧美熟妇一区二区三区蜜桃视频 國產美女AV操逼網站| 亚洲AV成人无码精品区| 人人操人人爱人人拍| 国产精品久久AV电影| 大地8免费高清视频观看大全| 国产精品一卡二卡三卡| 四虎看片| 成人黄色视频网站在线观看| 午夜99| 67194熟女| 91在线无码精品秘入口动作| 东京热视频在线观看| 久久久久久久毛片| 91av导航| 日日搔av一区二区三区| 丝袜乱伦| 超碰在线观看97| 91麻豆国产在线观看| 91网站在线免费观看| 日本黄色影院在线| av无码免费| 无码黄片免费| 香蕉成人A片视频| 久久伊人中文字幕| 伊人色综合网| 十八禁视频在线观看网站.www| 日本精品无码a62v在线| 日韩AV无码电影| 女人特级毛片18| 好看的中文字幕av| 一本大道东京热AV| 成片免费观看视频大全| 尤物av| 国产天堂视频| 在线成人AV| 亚洲欧美国产视频| 成人777| 国产亚洲99久久精品| 成人午夜天堂| 天堂国产| 在线你懂的| 婷婷日韩在线| 成人v| 日韩乱伦电影| 自慰喷水流白浆中文字幕| 91AV天天在线观看| 男人的天堂色婷婷| 欧美偷拍视频| 自拍偷拍福利视频网站| 俺去也www俺去也com| 久久久偷拍| 99青草在线视频| 精品素人在线| 日韩AV综合| 亲子乱婬一级A片| 久久免费成人| 一区二区三区观看| 青青草免费公开视频| 婷婷五月大香蕉| 亚洲精品18禁| 蜜桃Av噜噜一区二区| 国产在线成人视频| 天堂在线观看av| 国产二级片| 国产在线小视频| 国产成人小视频在线观看| www深夜成人a√在线| 国产一级黄色毛片| AV婷婷五月天| 91口爆| 久热热| 大奶AV| 一本大道东京热av无码| 91久久精品一区二区三区| 国产夫妻自拍AV| 精品福利在线观看| 亚洲日韩在线看| 人妻天天操| 精品操逼| 国产探花一区二区三区| 人人妻人人爱人人操| 91久久国产综合久久91| 欧美在线A| 亚洲中文娱乐| 夜夜狠狠躁日日| 美女乱伦视频| 欧美操B视频| 91人妻人人澡人人爽人人DVD| 午夜高清视频| 加勒比日韩无码| 黑人巨大精品欧美| 日韩中文字幕| 欧美在线一级片| 久久女人视频| 国产成人电影一区二区| 91香蕉国产在线观看软件| 天堂麻豆天美| 成人免费视频一区二区| 亚洲福利视频97| 午夜特级| 国产精品色哟哟| 秋霞理伦| 永久黄网站| 免费国产黄色视频网站| 蜜桃AV一区二区三区| 女人自慰在线观看| 亚洲人妻在线播放| 特黄视频| 一区二区三区四区五区无码| 老熟女17页一91| 永久久久久久久| 国产操屄视频| 在线观看视频国产| 婷婷综合网| 一区二区三区无码区| 无码人妻视频| 操逼视频网站免费| 无码三级在线观看| 豆花视频在线免费观看| www在线| eeuss在线| 小骚逼操死你| 中文字幕第72页| 成人A毛片| 2019人人操| 色逼高清| 精品免费在线观看| 91人妻一区二区三区无不码超满| 亚洲视频免费在线| 人人操人人干人人| 国产精品国产精品国产专区不| 先锋久久资源| 99成人国产精品视频| 毛片无遮挡| 国产在线激情视频| 日韩中文字幕精品| 亚洲国产另类精品| 亚洲日韩中字| 人人弄人人| 久99热| 国产A级片| 黑人vs亚洲人在线播放| 99久久99久久久精品棕色圆| 夜夜嗨av无码一区二区三区| 国产精品二区高清在线苍井空| 亚洲中文无码在线观看| 国产高清无码自拍| 日韩欧美黄| 亚洲综合一二三区| 国产操比视频| 国精产品一二三区| 在线观看日韩三级片av| 国内精品久久久久| 97免费视频在线观看| 中文字幕视频| 日本天堂在线| 欧美综合视频在线观看| 久久久久综合| 97久久精品| 四川少妇BBB凸凸凸BBB安慰我| 久久XX| 青青青国产在线| 欧美精产国品一二三区| 国产高清视频在线播放| 蜜桃在线无码| 天堂一区二区| 黄色激情在线| 乱伦小说五月天| 亚洲无码久久久| 激情五月天视频| 七区九区一区在线| 中日韩欧美一级A片免费| 91男女| 国精品无码一区二区三区在线秋菊 | 996久久| 日韩免费高清视频| 人人做人人做人人做,人人做全句下一| 亚洲中文字幕日韩在线| 天堂亚洲精品| 日本A∨| 熟女资源网| 人人爱人人操| 一区高清无码| 色欲网址| 俺去也av| 黄片网址| 日韩a片| 国产无码AV在线| 日本在线视频不卡| 久草视频在线播放| 亚洲中文娱乐| 欧美熟妇BBB搡BBB| 成人动漫免费观看| 亚洲无码播放| 91成人一区| 老司机精品| 免费国产h| 黄色亚洲| 国内成人AV| 国产21区| 成人做爰黄级A片免费看土方| 在线观看免费黄片| 日韩草逼| 老熟妇一区二区三区啪啪| 少婦揉BBBB揉BBBB揉| 亚洲五月六月| 最新福利视频| 久久人妻免费视频| 日韩无码AV电影| 亚洲最大福利视频| 色情小电影免费网站观看网址在线播| 99久久婷婷国产综合精品青牛牛| 亚洲成人三区| 国产精品无码白浆高潮| 日本大香蕉伊人| 日本一级黄| 特级大毛片| 日韩综合网| 久久AV片| 91香蕉视频在线播放| 日本三级韩三级99久久| 欧美操逼在线| 91视频电影| 日本的黄色视频| 久草成人| 久久波多野结衣| 成人免费乱码大片a毛片蜜芽| 久久久电影| 亚洲一级黄色片| 国产一级特黄A片| 亚洲成人性爱网站| 韩国免费一级a一片在线播放| av影音先锋| 色婷婷激情五月天| 日日干干| 黄色片在线看| 亚洲91精品| 老熟女一区二区三区| 国产成人免费做爰视频| 欧美人人爱| 亚洲免费视频一区| 久久毛片基地| 国产乱子伦一区二区三区视频| 漂亮人妻吃鸡啪啪哥哥真的好| 69超碰| 国产精品AV在线| 亚洲无码AV在线播放| 91丨牛牛丨国产| 蝌蚪窝免费视频| 欧美91视频| 99免费小视频| 精品视频在线看| 99r6热只有精品免费观看| 欧美综合视频在线观看| 亚洲无码黄色电影| 在线综合国产欧美| 狠狠干亚洲视频| 欧美日韩成人| 天天做天天干| 国产一级a毛一级a| 人妻视频网站| 日韩免费无码| 亚洲AV无码成人精品区国产| www.国产精品| 亚洲无aV在线中文字幕| 一级A片免费视频| 欧美一级免费观看| 蜜芽成人在线| 国产欧美一区二区三区四区 | 无码国产精品一区二区免费式直播 | 欧美色影院| 一级黄色片免费观看| 日韩精品无码av| 久久六月天| 69视频在线免费观看| 亚洲国产A片| 中文字幕无码乱伦| 国产a毛一级,a毛一级| 白嫩无码| 精品久久无码中文字幕| 五月婷婷视频在线观看| 国产精品久久久久久久久借妻| 欧美成人精品激情在线观看| 2019天天操| 国产一级a毛一级a毛观看视频网站www.jn | 男人午夜天堂| 亚洲AV无码成人| 日韩性爱视频网站| 国产永久免费| 青娱乐自拍视频| 69超碰| 成年人在线视频| 精品无码一区二区三区四区久久久软件| 很很日| 九九性视频| 日韩色妇| 91人人妻人人爽| 乱伦乱码| 免费成人在线看片黄| 91香蕉网| 亚洲小电影在线| 国产成人无码永久免费| 中文在线字幕电视剧免费平台| 精品人妻一区二区| 日韩小视频| 日韩视频一级| 靠逼国产| 怡红院一区二区| 加勒比综合网| 久青草资源福利视频| 天天爽夜夜爽人人爽| 青青草激情视频| 大香蕉久草| 美女被操网站| 日韩成人无码全裸视频| 无码精品一区二区三区在线观看| 亚洲一区图片| www亚洲视频| 91探花秘在线播放偷拍| 一级A片免费视频| 蜜臀久久99精品久久久老牛影视 | 国产无码久久久| 欧美做受高潮白| 99久久99久久久精品棕色圆| av天堂中文字幕| 青青草91| 大香蕉最新国产2025| 日韩中文字幕一区二区三区| 黄色毛片在线播放| 蜜桃av无码一区三区| 不卡不在线中文| 边摸边操| 日本高清色清di免费观看| 一级a在线| 无码高潮视频| 日本99热| 国产第一页在线观看| 日本三级片网站在线观看| 亚洲无码黄色片| 日韩欧美在中文| 波多野在线视频| 青青青操| 亚洲精品久久久久毛片A级牛奶| 国产乱子伦一区二区三区视频| 伊人婷婷大香蕉| 囯产精品久久久久久久| 国内自拍偷拍| 99久久精品一区二区成人| www.xxx| 日本三级韩三级99久久| 精品国产乱子伦一区二区三区最新章 | 国产成人精品二三区麻豆| 影音先锋成人网| 欧美第一网站| 东方AV在| 久久精品国产99精品国产亚洲性色| 欧美成人视频在线观看| 黄色视频在线| 性生活无码视频| 久久精品一区二区三区蜜芽的特点| 欧美操B视频| 麻豆视屏| 亚洲黄片免费看| 国产精品久久久一区二区三区| 最新亚洲无码在线观看| 亚洲最大黄色视频| 久操精品| 在线不卡无码| www九九热| 中文字幕精品在线| 日韩免费性爱视频| 国产精品无码ThePorn| 国产裸体美女网站| 欧美日韩中文在线观看| 欧美激情在线观看| 日韩欧美三级| 国产青草视频在线观看| 美女极度色诱图片www视频| 国产黄片免费观看| 男女啪网站| 波多野结衣一区二区三区在线观看| 午夜99| 国产亚洲久一区二区| 国产亚洲视频免费观看| 91人妻人人澡人人爽人人精 | 天天色图片| 免费做a爰片77777| www.四虎成人网站| 天堂网2018| 国产三级av在线| 奇米四色秒播| 澳门无码视频| 午夜精品久久久久久久| 日韩日日操| 一级性爽A√毛片| 天天做| 婷婷亚洲精品| 人人上人人干| 三级片在线观看网站| 91超碰在线播放| 91探花足浴店少妇在线| 免费A片在线| 九九福利视频| 国外亚洲成AV人片在线观看| 成人做爰黄A片免费视频网站野外 国产成人午夜精品无码区久久麻豆 | 色色三区| 欧美操逼图片| jzzijzzij亚洲成熟少妇在线观看 九色蝌蚪9l视频蝌蚪9l视频成人熟妇 | 91一区| 伊人逼逼| 天天天天天天干| 国产一级a免一级a免费| 2021无码| 四虎亚洲无码| 岛国AV免费看| 日韩免费网| 午夜无码精品一区二区三区99午| 黄频美女日本免费| 一本无码高清| 亚洲女人天堂| 熟女老阿V8888AV| 91人人澡| 日本中文字幕中文翻译歌词| 精品视频一区二区三区四区| 欧美四虎| 亚洲精品91| 十八女人高潮A片免费| 欧美成人一区二区三区| 亚洲无码黄色片| 久久精品国产亚洲| 亚洲视频观看| 亚洲精品内射| 仓井空一区二区三区| 三级片欧美| 动漫av网站| 日韩人妻精品无码制服| 一级片网址| 大香蕉日韩| 91大神shunv| 亚洲色视频| 91干逼| 汇聚全球淫荡熟女| jizz国产精品| 青草在线视频| 黄片二区| 人妻精品综合码| 色天堂在线观看| 午夜神马影院| 色天堂在线观看| 69成人视频| 日韩一欧美| 久久久久逼| 久操手机在线| 婷婷久久综| 国语一区| 婷婷大香蕉| 亚洲黄片大全| 人妻懂色av粉嫩av浪潮av| 亚洲毛片网| 色国产在线| 俺来也官网欧美久久精品| 丁香五月综合网| 午夜av电影| 亚洲日韩AV在线| 污网站免费观看| 老鸭窝久久| 精品人妻一区| 熟女在线视频| 亚洲三级视频| 婷色| 自拍偷拍福利视频网站| 成人无码网站| 北条麻妃AV在线播放| 北条麻妃在线播放一区| 国产午夜在线观看| 欧美国产第一页| 91大长腿美女花外围在线观看| 亚洲精品无码视频在线观看| 国产欧美另类| 激情婷婷五月天| 视频一区二区三区在线观看| 最近中文字幕中文翻译歌词| 成人无码视频| 一本大道DVD中文字幕| 色色综合热| 就去色色五月丁香婷婷久久久| 北条麻妃无码精品AV| 欧美综合自拍| 欧美性爱一级视频| 亚洲视频在线免费播放| 亚洲3p| 欧美激情内射| 国产精品无码永久免费不卡| 国产高清a| 中文字幕777| 国产18水真多18精品| 国产激情艹逼| 79色色| 欧美午夜精品久久久久久3D| aaa国产精品| 亚洲视频一区| 国产一区二区三区免费视频| 最新中文字幕av| 69激情网| 中文字幕色情| 成人视频免费网站| 中文无码第一页| 一级片国产| 手机看片午夜福利网| 久久精品视频99| 日韩四区| 国产99久久久精品| 亚洲色吧| 五月天最新网址| 亚洲精品久久久久久久久久久| 91高清无码视频| 亚洲av无码精品| 一区二区av| 亚洲视频免费播放| 亚洲最大福利视频| 亚洲熟女一区二区| 久久你懂的| 四川少妇BBB凸凸凸BBB安慰我| 亚洲va国产va天堂va久久| 亚洲成人色色| 午夜特片| 一级a一级a爰片免费免免中国A片| 亚洲国产操逼| 亚洲一区二区三区无码| 日韩日屄视频| 一级无码在线观看| 伊人色五月天| 中日韩中文字幕一区二区区别| 国产成人+综合亚洲+天堂| 日本免费黄色电影| 国产精品tv| 亚洲激情内射| 五月大香蕉| 人妻熟女88AⅤ| 伊人色爱| 日本50路熟女| 日韩A级片| 午夜高清无码| 中文字幕视频在线播放| 日韩三级片无码| www.91AV| 亚州v| 亚洲色图88| 91一级A片在线观看| 欧美日韩免费在线播放电影在线播放电影在线播放电影免费 | 天天做天天干| 91色色色| 日本色色色| 黄色成人网站在线| 激情国产视频| 日韩天堂网| 12—13女人毛片毛片| 91久久久青青青青草| 影音先锋男人天堂| 91.射| 9l视频自拍蝌蚪9l视频成人| 米奇电影777无码| 久久嫩草精品久久久久精| 欧美视频一区| 99婷婷| 日本无码视频在线观看| 久久一级视频| 人妻碰碰| 午夜成人网站| 手机成人在线视频| 熟妇人妻丰满久久久久久久无码 | 人人射人人操| A视频在线观看| 亚洲无码一区二区在线观看| 99精品免费| 日韩成人精品视频| 丁香在线视频| 91好爽| 欧美日本国产| 五月开心激情网| 日本免费视频| 国产精品无码白浆高潮| 国产精品热| 中文字幕一区二区6页| 韩日中文字幕| 无套免费视频欧美| 激情国产视频| 99在线精品视频免费观看20| 国产一级黄色录像| 一区二区三区中文字幕| 成人中文字幕在线| 自拍av在线| 欧美日韩A| 成人一区二区三区四区| 狠狠色婷婷7777| av在线天堂| 91视频免费观看| 亚洲av不卡| 亚洲无码1| 色五月婷婷五月天激情| 99插插插| 国产秘精品区二区三区日本| 波多野结衣国产区42部| 成人在线综合| 精品人伦一区二区三区| 俺去俺来也WWW色老板| 一级午夜| 精品一区无码| 熟妇人妻中文AV无码| 91成人免费电影| 俺去夜| 国产婷婷| 国产黄片自拍| 骚骚网站| 亚洲天堂在线免费| 久久久精品网站| 一区久久| 337p大胆色噜噜噜噜噜| 水果派AV| 蜜桃传媒一区二区| 亚洲午夜无码精品专区| 99插插插| 国产精品色在线| 国产黄片免费视频| 人妻av中文字幕| 午夜无码人妻AV| 肏屄网站| 天天干夜夜操熟女| 婷婷丁香花| 热久色| 黄色片国产| 亚洲无码精品在线观看| 国产精品久久久久野外| 炮友露脸青楼传媒刘颖儿| 青操在线| 岛国电影av| 9999国产精品| 美女综合网| 久久精品一区二区三区四区五区| 国产精品久久久久久久久A| 欧美国产另类| 超碰伊人大香蕉| 熟女乱论| 欧美中文字幕在线观看| 一起操逼| 日本成人一区二区| 奇米97| 在线观看黄色av| 国产系列每日更新| 亚洲欧美成人| 一本色道久久无码人妻精品69| 青草国产视频| 亚洲激情网| 五月天网址| 黄色视频免费在线看| 可以看的毛片| 俺来也俺也啪WWW色| 国产乱婬AAAA片视频| 在线成人小视频| 中国精品77777777| 91在线无码精品秘国产-百度| 欧美在线网站| 久草新| 国产精品国产三级国产| 免费看黄色一级片| 高清无码视频免费观看| 黄色免费在线观看网站| 成人免费操| 3p绿帽黑人看自己老婆| 西西444WWW大胆无| 亚洲AV久久无码| 四虎成人无码| 一级生活片| 亚洲第一色在线| 成人av免费观看| 伊人精品视频| 777免费观看成人电影视频| 毛片无遮挡| 中文字幕成人无码| 亚洲av资源| 亚洲国产视频在线观看| 无码做爱视频| 99热在线看| 国产成人97精品免费看片| 欧美A片免费| 六月激情婷婷| 四川搡BBBBB搡BBB| 色色色热| 亚洲高清在线观看视频| 婷婷成人小说| 97人人色| 操逼操| 香蕉在线播放| 五月婷婷网站| 久久无码区| 国产尤物| 五月丁香综合激情| www.777熟女人妻| 欧美午夜黄片| 亚洲狼人| 天堂中文在线播放| 中文字幕人妻丰满熟妇| 激情小视频在线| 美女操B| 中文国产| 国产精品操逼网站| 蜜臀久久99精品久久久兰草影视| 影音先锋成人电影| 操逼网址大全| 一区二区三区在线免费观看| av大片在线观看| 日韩无码视频网| 黄色毛片网站| 91久久午夜无码鲁丝片久久人妻| 51午夜| 91日韩无码| 日韩一区在线视频| 国产一级精品视频| 九九性爱网| 五月婷婷丁香| 国产草莓视频| 免费在线观看黄| 亚洲人免费视频| 首页-91n| 婷婷久热| 黄页网址在线观看| 久久久久久国际四虎免费精品视频| 亚洲天堂无码AV| 狠狠的日| 中文字幕在线成人| 玉米地一级婬片A片| 欧产日产国产swag| 91免费国产视频| 无码草| 大香蕉伊人在线观看视频| 欧美A级黄片| 麻豆午夜成人无码电影| 中文成人在线| 在线播放无码| 亚洲少妇网| 日韩日屄视频| 久久久无码AV| 日本中文字幕在线视频| 亚洲色a| 大香蕉99热| 欧美夜夜操| AV大片免费看| 欧美三P囗交做爰XXXⅩ| 欧美午夜影院| 性BBwBBwBBwBBw禽| 久久不射网站| www久久| 亚洲AV中文无码| 国产美女精品久久AV爽| 丁香婷婷激情五月| 国产一级a毛一级a做免费的视频l 精品国产免费观看久久久_久久天天 | 麻豆视频一区| 麻豆视屏| 狠狠干影院| 国产无码电影在线观看| 天天爽天天操| 日韩成人三级片| 欧美精品A级片| 蜜桃久久久亚洲精品| 亚洲成人人妻| 老司机免费福利视频| 国产成人一区二区无码| 日本在线免费观看| 福利视频一区二区| 在线成人小视频| 成人免费在线观看| 美女高潮网站| 久久精品一区二区三区四区五区| 人人爱人人摸人人操| 444444免费高清在线观看电视剧的注意| 国产精品久久毛片A片| 欧美日韩中文视频| 国产女人在线| 亚洲国产激情视频| 亚洲国产av一区| 在线观看黄色av| 国产97在线视频| 亚洲AV无码乱码AV| 18av在线观看| 国产第页| AV毛片| 青娱乐欧美| 国产日韩欧美成人| 国产免费一区二区三区最新不卡| 久久足交| 99国产精品久久久久久久| 中文字幕中文字幕| 黄色视频免费国产| 无码不卡一区| 欧美成人精品无码| 欧美日韩一级A片| 日韩av在线看| 男人天堂网站| 色视频在线| 日本熟妇无码一区二区| 色秘乱码一区二区三区| 可以免费看的av| www.日逼| 亚洲久久色| 男女av在线| 色婷婷六月天| 亚洲无码av网站| 午夜色色福利| 国产中文字幕在线视频| 国产区一区| 欧美成人在线免费| 黄色操逼视频| 亚洲欧美日韩一区二区| a久久| 国产精品国产三级国产专区52| a在线观看| 91人妻无码精品一区二区| 日本理论片一道本| 亚洲成人第一网站| 黄色激情五月天| 人妻精品一区二区| 大香蕉免费| 白丝久久| AA片在线观看视频在线播放| 一区二区国产精品| 午夜福利澳| 很很撸在线视频| 国内操B电影| 4438成人网| 国产免费高清| 成人在线第一页| 亚洲高潮| 精品无码一区二区| 欧美激情五月天| 亚洲精品久久久久久久久豆丁网| 男人的天堂网页| 大香蕉在线视频观看| 亚洲综合伊人| 亚洲毛片在线观看| 欧洲亚洲视频| 日韩十八禁网站| 波多野吉衣中文字幕| 国产老熟女高潮毛片A片仙踪林| 成人免费毛片AAAAAA片| 成人无码区免费| 青青草社区| 日韩在线观看网址| 欧美日韩免费观看视频| 一级黄片学生妹| 亚洲欧美性爱| 2021无码| 欧美成人激情视频| 视频一区二区三| 成人网中文字幕| 亚洲四房播| 亚洲国产A片| 亚洲色播放| 久草成人| 久久国产精品网站| 91在线| 亚洲视频高清无码| 久久精品视频一区| 日韩精品视频免费在线观看| 中文字幕五月天| 东京亚洲无码| 无毛片| 日韩人妻精品无码久久边| 大香蕉伊人久久| 在线视频第一页| 91成人免费电影| 91人妻人人人人爽| 北条麻妃在线一区| 小明看台湾成人永久免费视频网站 | 国产avwww| 成人大香蕉视频| 一级黄片在线| 超碰自拍97| 亚洲视频网址| 佐山爱人妻无码蜜桃| 特级丰满少妇免费观看| 99re国产| 国产91在线视频| 无码一级片| 五月婷婷影院| 免费国产黄色| 国产成人99久久亚洲综合精品| 久操视频在线播放| 国产欧美综合视频| www.俺来也| 黄色伊人网| www.一区二区三区| www欧美日韩| 中文字幕人妻互换av久久| 午夜成人无码| 亚洲中文字幕一| 青娱乐国产在线视频| 91免费高清视频| 婷婷五月综合在线| 日韩av免费看| 壁特壁视频在线观看|