-
-
-
- Apache Doris(incubating) is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the Apache Incubator. Incubation is required of all newly accepted projects until a further review indicates that the infrastructure, communications, and decision making process have stabilized in a manner consistent with other successful ASF projects. While incubation status is not necessarily a reflection of the completeness or stability of the code, it does indicate that the project has yet to be fully endorsed by the ASF.
-
-
-
-{% endblock %}
diff --git a/docs/website/source/conf.py b/docs/website/source/conf.py
deleted file mode 100644
index 72c107cd305b66..00000000000000
--- a/docs/website/source/conf.py
+++ /dev/null
@@ -1,199 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Configuration file for the Sphinx documentation builder.
-#
-# This file does only contain a selection of the most common options. For a
-# full list see the documentation:
-# http://www.sphinx-doc.org/en/master/config
-
-# -- Path setup --------------------------------------------------------------
-
-# If extensions (or modules to document with autodoc) are in another directory,
-# add these directories to sys.path here. If the directory is relative to the
-# documentation root, use os.path.abspath to make it absolute, like shown here.
-#
-# import os
-# import sys
-# sys.path.insert(0, os.path.abspath('.'))
-
-#import t3SphinxThemeRtd
-
-# -- Project information -----------------------------------------------------
-
-project = u'Doris Documentations'
-copyright = u'2019, Apache Doris(Incubating)'
-author = u'Apache Doris(Incubating)'
-
-# The short X.Y version
-version = u'0.11.0'
-# The full version, including alpha/beta/rc tags
-release = u'0.11.0'
-
-
-# -- General configuration ---------------------------------------------------
-
-# If your documentation needs a minimal Sphinx version, state it here.
-#
-# needs_sphinx = '1.0'
-
-# Add any Sphinx extension module names here, as strings. They can be
-# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
-# ones.
-extensions = [
- 'sphinx.ext.autodoc',
- 'recommonmark',
- 'sphinx_markdown_tables'
-]
-
-# Add any paths that contain templates here, relative to this directory.
-templates_path = ['_templates']
-
-# The suffix(es) of source filenames.
-# You can specify multiple suffix as a list of string:
-#
-# source_suffix = ['.rst', '.md']
-# source_suffix = '.rst'
-source_suffix = {
- '.rst': 'restructuredtext',
- '.txt': 'markdown',
- '.md': 'markdown',
-}
-
-# The master toctree document.
-master_doc = 'index'
-
-# The language for content autogenerated by Sphinx. Refer to documentation
-# for a list of supported languages.
-#
-# This is also used if you do content translation via gettext catalogs.
-# Usually you set "language" from the command line for these cases.
-language = None
-
-# List of patterns, relative to source directory, that match files and
-# directories to ignore when looking for source files.
-# This pattern also affects html_static_path and html_extra_path.
-exclude_patterns = []
-
-# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = None
-
-# -- Options for HTML output -------------------------------------------------
-
-# The theme to use for HTML and HTML Help pages. See the documentation for
-# a list of builtin themes.
-#
-html_theme = "sphinx_rtd_theme"
-#html_theme = "t3SphinxThemeRtd"
-#html_theme_path = [t3SphinxThemeRtd.get_html_theme_path()]
-
-# Theme options are theme-specific and customize the look and feel of a theme
-# further. For a list of options available for each theme, see the
-# documentation.
-#
-# html_theme_options = {}
-
-# Add any paths that contain custom static files (such as style sheets) here,
-# relative to this directory. They are copied after the builtin static files,
-# so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['_static']
-
-# Custom sidebar templates, must be a dictionary that maps document names
-# to template names.
-#
-# The default sidebars (for documents that don't match any pattern) are
-# defined by theme itself. Builtin themes are using these templates by
-# default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
-# 'searchbox.html']``.
-#
-# html_sidebars = {}
-
-
-# -- Options for HTMLHelp output ---------------------------------------------
-
-# Output file base name for HTML help builder.
-htmlhelp_basename = 'dorisdoc'
-
-
-# -- Options for LaTeX output ------------------------------------------------
-
-latex_elements = {
- # The paper size ('letterpaper' or 'a4paper').
- #
- # 'papersize': 'letterpaper',
-
- # The font size ('10pt', '11pt' or '12pt').
- #
- # 'pointsize': '10pt',
-
- # Additional stuff for the LaTeX preamble.
- #
- # 'preamble': '',
-
- # Latex figure (float) alignment
- #
- # 'figure_align': 'htbp',
-}
-
-# Grouping the document tree into LaTeX files. List of tuples
-# (source start file, target name, title,
-# author, documentclass [howto, manual, or own class]).
-latex_documents = [
- (master_doc, 'doris.tex', u'Doris Documentation',
- u'Apache Doris(Incubating)', 'manual'),
-]
-
-
-# -- Options for manual page output ------------------------------------------
-
-# One entry per manual page. List of tuples
-# (source start file, name, description, authors, manual section).
-man_pages = [
- (master_doc, 'Doris', u'Doris Documentation',
- [author], 1)
-]
-
-
-# -- Options for Texinfo output ----------------------------------------------
-
-# Grouping the document tree into Texinfo files. List of tuples
-# (source start file, target name, title, author,
-# dir menu entry, description, category)
-texinfo_documents = [
- (master_doc, 'Doris', u'Doris Documentation',
- author, 'Apache Doris(Incubating)', 'An MPP-based interactive SQL data warehouse for reporting and analysis',
- 'Miscellaneous'),
-]
-
-
-# -- Options for Epub output -------------------------------------------------
-
-# Bibliographic Dublin Core info.
-epub_title = project
-
-# The unique identifier of the text. This can be a ISBN number
-# or the project homepage.
-#
-# epub_identifier = ''
-
-# A unique identification for the text.
-#
-# epub_uid = ''
-
-# A list of files that should not be packed into the epub file.
-epub_exclude_files = ['search.html']
-
-html_search_language = 'zh'
-
-html_context = {
- # Enable the "Edit in GitHub link within the header of each page.
- 'display_github': True,
- # Set the following variables to generate the resulting github URL for each page.
- # Format Template: https://{{ github_host|default("github.com") }}/{{ github_user }}
- #/{{ github_repo }}/blob/{{ github_version }}{{ conf_py_path }}{{ pagename }}{{ suffix }}
- 'github_user': 'apache',
- 'github_repo': 'incubator-doris',
- 'github_version': 'master' ,
- 'conf_py_path' : '/docs/',
-}
-
-# -- Extension configuration -------------------------------------------------
diff --git a/docs/website/source/index.rst b/docs/website/source/index.rst
deleted file mode 100644
index 16bbc299d736f1..00000000000000
--- a/docs/website/source/index.rst
+++ /dev/null
@@ -1,590 +0,0 @@
-Introduction to Apache Doris (incubating)
-=========================================
-
-Apache Doris is an MPP-based interactive SQL data warehousing for
-reporting and analysis. Doris mainly integrates the technology of Google
-Mesa and Apache Impala. Unlike other popular SQL-on-Hadoop systems,
-Doris is designed to be a simple and single tightly coupled system, not
-depending on other systems. Doris not only provides high concurrent low
-latency point query performance, but also provides high throughput
-queries of ad-hoc analysis. Doris not only provides batch data loading,
-but also provides near real-time mini-batch data loading. Doris also
-provides high availability, reliability, fault tolerance, and
-scalability. The simplicity (of developing, deploying and using) and
-meeting many data serving requirements in single system are the main
-features of Doris.
-
-1. Background
--------------
-
-In Baidu, the largest Chinese search engine, we run a two-tiered data
-warehousing system for data processing, reporting and analysis. Similar
-to lambda architecture, the whole data warehouse comprises data
-processing and data serving. Data processing does the heavy lifting of
-big data: cleaning data, merging and transforming it, analyzing it and
-preparing it for use by end user queries; data serving is designed to
-serve queries against that data for different use cases. Currently data
-processing includes batch data processing and stream data processing
-technology, like Hadoop, Spark and Storm; Doris is a SQL data warehouse
-for serving online and interactive data reporting and analysis querying.
-
-Prior to Doris, different tools were deployed to solve diverse
-requirements in many ways. For example, the advertising platform needs
-to provide some detailed statistics associated with each served ad for
-every advertiser. The platform must support continuous updates, both new
-rows and incremental updates to existing rows within minutes. It must
-support latency-sensitive users serving live customer reports with very
-low latency requirements and batch ad-hoc multiple dimensions data
-analysis requiring very high throughput. In the past,this platform was
-built on top of sharded MySQL. But with the growth of data, MySQL cannot
-meet the requirements. Then, based on our existing KV system, we
-developed our own proprietary distributed statistical database. But, the
-simple KV storage was not efficient on scan performance. Because the
-system depends on many other systems, it is very complex to operate and
-maintain. Using RPC API, more complex querying usually required code
-programming, but users wants an MPP SQL engine. In addition to
-advertising system, a large number of internal BI Reporting / Analysis,
-also used a variety of tools. Some used the combination of SparkSQL /
-Impala + HDFS / HBASE. Some used MySQL to store the results that were
-prepared by distributed MapReduce computing. Some also bought commercial
-databases to use.
-
-However, when a use case requires the simultaneous availability of
-capabilities that cannot all be provided by a single tool, users were
-forced to build hybrid architectures that stitch multiple tools
-together. Users often choose to ingest and update data in one storage
-system, but later reorganize this data to optimize for an analytical
-reporting use-case served from another. Our users had been successfully
-deploying and maintaining these hybrid architectures, but we believe
-that they shouldn’t need to accept their inherent complexity. A storage
-system built to provide great performance across a broad range of
-workloads provides a more elegant solution to the problems that hybrid
-architectures aim to solve. Doris is the solution. Doris is designed to
-be a simple and single tightly coupled system, not depending on other
-systems. Doris provides high concurrent low latency point query
-performance, but also provides high throughput queries of ad-hoc
-analysis. Doris provides bulk-batch data loading, but also provides near
-real-time mini-batch data loading. Doris also provides high
-availability, reliability, fault tolerance, and scalability.
-
-Generally speaking, Doris is the technology combination of Google Mesa
-and Apache Impala. Mesa is a highly scalable analytic data storage
-system that stores critical measurement data related to Google’s
-Internet advertising business. Mesa is designed to satisfy complex and
-challenging set of users’ and systems’ requirements, including near
-real-time data ingestion and query ability, as well as high
-availability, reliability, fault tolerance, and scalability for large
-data and query volumes. Impala is a modern, open-source MPP SQL engine
-architected from the ground up for the Hadoop data processing
-environment. At present, by virtue of its superior performance and rich
-functionality, Impala has been comparable to many commercial MPP
-database query engine. Mesa can satisfy the needs of many of our storage
-requirements, however Mesa itself does not provide a SQL query engine;
-Impala is a very good MPP SQL query engine, but the lack of a perfect
-distributed storage engine. So in the end we chose the combination of
-these two technologies.
-
-Learning from Mesa’s data model, we developed a distributed storage
-engine. Unlike Mesa, this storage engine does not rely on any
-distributed file system. Then we deeply integrate this storage engine
-with Impala query engine. Query compiling, query execution coordination
-and catalog management of storage engine are integrated to be frontend
-daemon; query execution and data storage are integrated to be backend
-daemon. With this integration, we implemented a single, full-featured,
-high performance state the art of MPP database, as well as maintaining
-the simplicity.
-
-2. System Overview
-------------------
-
-Doris’ implementation consists of two daemons: frontend (FE) and backend
-(BE). The following figures gives the overview of architecture and
-usage.
-
-.. figure:: https://raw.githubusercontent.com/apache/incubator-doris/master/docs/resources/images/palo_architecture.jpg
- :alt: Doris Architecture
-
- Doris Architecture
-
-Frontend daemon consists of query coordinator and catalog manager. Query
-coordinator is responsible for receiving user’s sql queries, compiling
-queries and managing queries execution. Catalog manager is responsible
-for managing metadata such as databases, tables, partitions, replicas
-and etc. Several frontend daemons could be deployed to guarantee
-fault-tolerance, and load balancing.
-
-Backend daemon stores the data and executes the query fragments. Many
-backend daemons could also be deployed to provide scalability and
-fault-tolerance.
-
-A typical Doris cluster generally composes of several frontend daemons
-and dozens to hundreds of backend daemons.
-
-Clients can use MySQL-related tools to connect any frontend daemon to
-submit SQL query. The frontend receives the query and compiles it into
-query plans executable by the backends. Then frontend sends the query
-plan fragments to backend. Backends will build a query execution DAG.
-Data is fetched and pipelined into the DAG. The final result response is
-sent to client via frontend. The distribution of query fragment
-execution takes minimizing data movement and maximizing scan locality as
-the main goal. Because Doris is designed to provide interactive
-analysis, so the average execution time of queries is short. Considering
-this, we adopt query re-execution to meet the fault tolerance of query
-execution.
-
-A table is splitted into many tablets. Tablets are managed by backends.
-The backend daemon could be configured to use multiple directories. Any
-directory’s IO failure doesn’t influence the normal running of backend
-daemon. Doris will recover and rebalance the whole cluster automatically
-when necessary.
-
-3. Frontend
------------
-
-In-memory catalog, multiple frontends, MySQL networking protocol,
-consistency guarantee, and two-level table partitioning are the main
-features of Doris’ frontend design.
-
-3.1 In-Memory Catalog
-~~~~~~~~~~~~~~~~~~~~~
-
-Traditional data warehouse always uses a RDBMS database to store their
-catalog metadata. In order to produce query execution plan, frontend
-needs to look up the catalog metadata. This kind of catalog storage may
-be enough for low concurrent ad-hoc analysis queries. But for online
-high concurrent queries, its performance is very bad,resulting in
-increased response latency. For example, Hive metadata query latency is
-sometimes up to tens of seconds or even minutes. In order to speedup the
-metadata access, we adopt the in-memory catalog storage.
-
-.. figure:: ./resources/images/log_replication.jpg
- :alt: log replication
-
- log replication
-
-In-memory catalog storage has three functional modules: real-time memory
-data structures, memory checkpoints on local disk and an operation relay
-log. When modifying catalog, the mutation operation is written into the
-log file firstly. Then, the mutation operation is applied into the
-memory data structures. Periodically, a thread does the checkpoint that
-dumps memory data structure image into local disk. Checkpoint mechanism
-enables the fast startup of frontend and reduces the disk storage
-occupancy. Actually, in-memory catalog also simplifies the
-implementation of multiple frontends.
-
-3.2 Multiple Frontends
-~~~~~~~~~~~~~~~~~~~~~~
-
-Many data warehouses only support single frontend-like node. There are
-some systems supporting master and slave deploying. But for online data
-serving, high availability is an essential feature. Further, the number
-of queries per seconds may be very large, so high scalability is also
-needed. In Doris, we provide the feature of multiple frontends using
-replicated-state-machine technology.
-
-Frontends can be configured to three kinds of roles: leader, follower
-and observer. Through a voting protocol, follower frontends firstly
-elect a leader frontend. All the write requests of metadata are
-forwarded to the leader, then the leader writes the operation into the
-replicated log file. If the new log entry will be replicated to at least
-quorum followers successfully, the leader commits the operation into
-memory, and responses the write request. Followers always replay the
-replicated logs to apply them into their memory metadata. If the leader
-crashes, a new leader will be elected from the leftover followers.
-Leader and follower mainly solve the problem of write availability and
-partly solve the problem of read scalability.
-
-Usually one leader frontend and several follower frontends can meet most
-applications’ write availability and read scalability requirements. For
-very high concurrent reading, continuing to increase the number of
-followers is not a good practice. Leader replicates log stream to
-followers synchronously, so adding more followers will increases write
-latency. Like Zookeeper,we have introduced a new type of frontend node
-called observer that helps addressing this problem and further improving
-metadata read scalability. Leader replicates log stream to observers
-asynchronously. Observers don’t involve leader election.
-
-The replicated-state-machine is implemented based on BerkeleyDB java
-version (BDB-JE). BDB-JE has achieved high availability by implementing
-a Paxos-like consensus algorithm. We use BDB-JE to implement Doris’ log
-replication and leader election.
-
-3.3 Consistency Guarantee
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-If a client process connects to the leader, it will see up-to-date
-metadata, so that strong consistency semantics is guaranteed. If the
-client connects to followers or observers, it will see metadata lagging
-a little behind of the leader, but the monotonic consistency is
-guaranteed. In most Doris’ use cases, monotonic consistency is accepted.
-
-If the client always connects to the same frontend, monotonic
-consistency semantics is obviously guaranteed; however if the client
-connects to other frontends due to failover, the semantics may be
-violated. Doris provides a SYNC command to guarantee metadata monotonic
-consistency semantics during failover. When failover happens, the client
-can send a SYNC command to the new connected frontend, who will get the
-latest operation log number from the leader. The SYNC command will not
-return to client as long as local applied log number is still less than
-fetched operation log number. This mechanism can guarantee the metadata
-on the connected frontend is newer than the client have seen during its
-last connection.
-
-3.4 MySQL Networking Protocol
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-MySQL compatible networking protocol is implemented in Doris’ frontend.
-Firstly, SQL interface is preferred for engineers; Secondly,
-compatibility with MySQL protocol makes the integrating with current
-existing BI software, such as Tableau, easier; Lastly, rich MySQL client
-libraries and tools reduce our development costs, but also reduces the
-user’s using cost.
-
-Through the SQL interface, administrator can adjust system
-configuration, add and remove frontend nodes or backend nodes, and
-create new database for user; user can create tables, load data, and
-submit SQL query.
-
-Online help document and Linux Proc-like mechanism are also supported in
-SQL. Users can submit queries to get the help of related SQL statements
-or show Doris’ internal running state.
-
-In frontend, a small response buffer is allocated to every MySQL
-connection. The maximum size of this buffer is limited to 1MB. The
-buffer is responsible for buffering the query response data. Only if the
-response is finished or the buffer size reaches the 1MB,the response
-data will begin to be sent to client. Through this small trick, frontend
-can re-execution most of queries if errors occurred during query
-execution.
-
-3.5 Two-Level Partitioning
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Like most of the distributed database system, data in Doris is
-horizontally partitioned. However, a single-level partitioning rule
-(hash partitioning or range partitioning) may not be a good solution to
-all scenarios. For example, there have a user-based fact table that
-stores rows of the form (date, userid, metric). Choosing only hash
-partitioning by column userid may lead to uneven distribution of data,
-when one user’s data is very large. If choosing range partitioning
-according to column date, it will also lead to uneven distribution of
-data due to the likely data explosion in a certain period of time.
-
-Therefore we support the two-level partitioning rule. The first level is
-range partitioning. User can specify a column (usually the time series
-column) range of values for the data partition. In one partition, the
-user can also specify one or more columns and a number of buckets to do
-the hash partitioning. User can combine with different partitioning
-rules to better divide the data. Figure 4 gives an example of two-level
-partitioning.
-
-Three benefits are gained by using the two-level partitioning mechanism.
-Firstly, old and new data could be separated, and stored on different
-storage mediums; Secondly, storage engine of backend can reduce the
-consumption of IO and CPU for unnecessary data merging, because the data
-in some partitions is no longer be updated; Lastly,every partition’s
-buckets number can be different and adjusted according to the change of
-data size.
-
-.. code:: sql
-
- -- Create partitions using CREATE TABLE --
- CREATE TABLE example_tbl (
- `date` DATE,
- userid BIGINT,
- metric BIGINT SUM
- ) PARTITION BY RANGE (`date`) (
- PARTITION p201601 VALUES LESS THAN ("2016-02-01"),
- PARTITION p201602 VALUES LESS THAN ("2016-03-01"),
- PARTITION p201603 VALUES LESS THAN ("2016-04-01"),
- PARTITION p201604 VALUES LESS THAN ("2016-05-01")
- ) DISTRIBUTED BY HASH(userid) BUCKETS 32;
-
- -- Add partition using ALTER TABLE --
- ALTER TABLE example_tbl ADD PARTITION p201605 VALUES LESS THAN ("2016-06-01");
-
-4. Backend
-----------
-
-4.1 Data Storage Model
-~~~~~~~~~~~~~~~~~~~~~~
-
-Doris combines Google Mesa’s data model and ORCFile / Parquet storage
-technology.
-
-Data in Mesa is inherently multi-dimensional fact table. These facts in
-table typically consist of two types of attributes: dimensional
-attributes (which we call keys) and measure attributes (which we call
-values). The table schema also specifies the aggregation function F: V
-×V → V which is used to aggregate the values corresponding to the same
-key. To achieve high update throughput, Mesa loads data in batch. Each
-batch of data will be converted to a delta file. Mesa uses MVCC approach
-to manage these delta files, and so to enforce update atomicity. Mesa
-also supports creating materialized rollups, which contain a column
-subset of schema to gain better aggregation effect.
-
-Mesa’s data model performs well in many interactive data service, but it
-also has some drawbacks: 1. Users have difficulty in understanding key
-and value space, as well as aggregation function, especially when they
-rarely have such aggregation demand in analysis query scenarios.
-
-2. In order to ensure the aggregation semantic, count operation on a
- single column must read all columns in key space, resulting in a
- large number of additional read overheads. There is also unable to
- push down the predicates on the value column to storage engine, which
- also leads to additional read overheads.
-
-3. Essentially, it is still a key-value model. In order to aggregate the
- values corresponding to the same key, all key columns must store in
- order. When a table contains hundreds of columns, sorting cost
- becomes the bottleneck of ETL process.
-
-To solve these problems, we introduce ORCFile / Parquet technology
-widely used in the open source community, such as MapReduce + ORCFile,
-SparkSQL + Parquet, mainly used for ad-hoc analysis of large amounts of
-data with low concurrency. These data does not distinguish between key
-and value. In addition, compared with the row-oriented database,
-column-oriented organization is more efficient when an aggregate needs
-to be computed over many rows but only for a small subset of all columns
-of data, because reading that smaller subset of data can be faster than
-reading all data. And columnar storage is also space-friendly due to the
-high compression ratio of each column. Further, column support
-block-level storage technology such as min/max index and bloom filter
-index. Query executor can filter out a lot of blocks that do not meet
-the predicate, to further improve the query performance. However, due to
-the underlying storage does not require data order, query time
-complexity is linear corresponding to the data volume.
-
-Like traditional databases, Doris stores structured data represented as
-tables. Each table has a well-defined schema consisting of a finite
-number of columns. We combine Mesa data model and ORCFile/Parquet
-technology to develop a distributed analytical database. User can create
-two types of table to meet different needs in interactive query
-scenarios.
-
-In non-aggregation type of table, columns are not distinguished between
-dimensions and metrics, but should specify the sort columns in order to
-sort all rows. Doris will sort the table data according to the sort
-columns without any aggregation. The following figure gives an example
-of creating non-aggregation table.
-
-.. code:: sql
-
- -- Create non-aggregation table --
- CREATE TABLE example_tbl (
- `date` DATE,
- id BIGINT,
- country VARCHAR(32),
- click BIGINT,
- cost BIGINT
- ) DUPLICATE KEY(`date`, id, country)
- DISTRIBUTED BY HASH(id) BUCKETS 32;
-
-In aggregation data analysis case, we reference Mesa’s data model, and
-distinguish columns between key and value, and specify the value columns
-with aggregation method, such as SUM, REPLACE, etc. In the following
-figure, we create an aggregation table like the non-aggregation table,
-including two SUM aggregation columns (clicks, cost). Different from the
-non-aggregation table, data in the table needs to be sorted on all key
-columns for delta compaction and value aggregation.
-
-.. code:: sql
-
- -- Create aggregation table --
- CREATE TABLE example_tbl (
- `date` DATE,
- id BIGINT,
- country VARCHAR(32),
- click BIGINT SUM,
- cost BIGINT SUM
- ) DISTRIBUTED BY HASH(id) BUCKETS 32;
-
-Rollup is a materialized view that contains a column subset of schema in
-Doris. A table may contain multiple rollups with columns in different
-order. According to sort key index and column covering of the rollups,
-Doris can select the best rollup for different query. Because most
-rollups only contain a few columns, the size of aggregated data is
-typically much smaller and query performance can greatly be improved.
-All the rollups in the same table are updated atomically. Because
-rollups are materialized, users should make a trade-off between query
-latency and storage space when using them.
-
-To achieve high update throughput, Doris only applies updates in batches
-at the smallest frequency of every minute. Each update batch specifies
-an increased version number and generates a delta data file, commits the
-version when updates of quorum replicas are complete. You can query all
-committed data using the committed version, and the uncommitted version
-would not be used in query. All update versions are strictly be in
-increasing order. If an update contains more than one table, the
-versions of these tables are committed atomically. The MVCC mechanism
-allows Doris to guarantee multiple table atomic updates and query
-consistency. In addition, Doris uses compaction policies to merge delta
-files to reduce delta number, also reduce the cost of delta merging
-during query for higher performance.
-
-Doris’ data file is stored by column. The rows are stored in sorted
-order by the sort columns in delta data files, and are organized into
-row blocks, each block is compressed by type-specific columnar
-encodings, such as run-length encoding for integer columns, then stored
-into separate streams. In order to improve the performance of queries
-that have a specific key, we also store a sparse sort key index file
-corresponding to each delta data file. An index entry contains the short
-key for the row block, which is a fixed size prefix of the first sort
-columns for the row block, and the block id in the data file. Index
-files are usually directly loaded into memory, as they are very small.
-The algorithm for querying a specific key includes two steps. First, use
-a binary search on the sort key index to find blocks that may contain
-the specific key, and then perform a binary search on the compressed
-blocks in the data files to find the desired key. We also store
-block-level min/max index into separate index streams, and queries can
-use this to filter undesired blocks. In addition to those basic columnar
-features, we also offers an optional block-level bloom filter index for
-queries with IN or EQUAL conditions to further filter undesired blocks.
-Bloom filter index is stored in a separate stream, and is loaded on
-demand.
-
-4.2 Data Loading
-~~~~~~~~~~~~~~~~
-
-Doris applies updates in batches. Three types of data loading are
-supported: Hadoop-batch loading, loading ,mini-batch loading.
-
-1. Hadoop-batch loading. When a large amount of data volume needs to be
- loaded into Doris, the hadoop-batch loading is recommended to achieve
- high loading throughput. The data batches themselves are produced by
- an external Hadoop system, typically at a frequency of every few
- minutes. Unlike traditional data warehouses that use their own
- computing resource to do the heavy data preparation, Doris could use
- Hadoop to prepare the data (shuffle, sort and aggregate, etc.). By
- using this approach, the most time-consuming computations are handed
- over to Hadoop to complete. This will not only improve computational
- efficiency, but also reduce the performance pressure of Doris cluster
- and ensure the stability of the query service. The stability of the
- online data services is the most important point.
-
-2. Loading. After deploying the fs-brokers, you can use Doris’ query
- engine to import data. This type of loading is recommended for
- incremental data loading.
-
-3. Mini-batch loading. When a small amount of data needs to be loaded
- into Doris, the mini-batch loading is recommended to achieve low
- loading latency. By using http interface, raw data is pushed into a
- backend. Then the backend does the data preparing computing and
- completes the final loading. Http tools could connect frontend or
- backend. If frontend is connected, it will redirect the request
- randomly to a backend.
-
-All the loading work is handled asynchronously. When load request is
-submitted, a label needs to be provided. By using the load label, users
-can submit show load request to get the loading status or submit cancel
-load request to cancel the loading. If the status of loading task is
-successful or in progress, its load label is not allowed to reuse again.
-The label of failed task is allowed to be reused.
-
-4.3 Resource Isolation
-~~~~~~~~~~~~~~~~~~~~~~
-
-1. Multi-tenancy Isolation:Multiple virtual cluster can be created in
- one pysical Doris cluster. Every backend node can deploy multiple
- backend processes. Every backend process only belongs to one virtual
- cluster. Virtual cluster is one tenancy.
-
-2. User Isolation: There are many users in one virtual cluster. You can
- allocate the resource among different users and ensure that all
- users’ tasks are executed under limited resource quota.
-
-3. Priority Isolation: There are three priorities isolation group for
- one user. User could control resource allocated to different tasks
- submitted by themselves, for example user’s query task and loading
- tasks require different resource quota.
-
-4.4 Multi-Medium Storage
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-Most machines in modern datacenter are equipped with both SSDs and HDDs.
-SSD has good random read capability that is the ideal medium for query
-that needs a large number of random read operations. However, SSD’s
-capacity is small and is very expensive, we could not deploy it at a
-large scale. HDD is cheap and has huge capacity that is suitable to
-store large scale data but with high read latency. In OLAP scenario, we
-find user usually submit a lot of queries to query the latest data (hot
-data) and expect low latency. User occasionally executes query on
-historical data (cold data). This kind of query usually needs to scan
-large scale of data and is high latency. Multi-Medium Storage allows
-users to manage the storage medium of the data to meet different query
-scenarios and reduce the latency. For example, user could put latest
-data on SSD and historical data which is not used frequently on HDD,
-user will get low latency when querying latest data while get high
-latency when query historical data which is normal because it needs scan
-large scale data.
-
-In the following figure, user alters partition ‘p201601’ storage_medium
-to SSD and storage_cooldown_time to ‘2016-07-01 00:00:00’. The setting
-means data in this partition will be put on SSD and it will start to
-migrate to HDD after the time of storage_cooldown_time.
-
-.. code:: sql
-
- ALTER TABLE example_tbl MODIFY PARTITION p201601
- SET ("storage_medium" = "SSD", "storage_cooldown_time" = "2016-07-01 00:00:00");
-
-4.5 Vectorized Query Execution
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Runtime code generation using LLVM is one of the techniques employed
-extensively by Impala to improve query execution times. Performance
-could gains of 5X or more are typical for representative workloads.
-
-But, runtime code generation is not suitable for low latency query,
-because the generation overhead costs about 100ms. Runtime code
-generation is more suitable for large-scale ad-hoc query. To accelerate
-the small queries (of course, big queries will also obtain benefits), we
-introduced vectorized query execution into Doris.
-
-Vectorized query execution is a feature that greatly reduces the CPU
-usage for typical query operations like scans, filters, aggregates, and
-joins. A standard query execution system processes one row at a time.
-This involves long code paths and significant metadata interpretation in
-the inner loop of execution. Vectorized query execution streamlines
-operations by processing a block of many rows at a time. Within the
-block, each column is stored as a vector (an array of a primitive data
-type). Simple operations like arithmetic and comparisons are done by
-quickly iterating through the vectors in a tight loop, with no or very
-few function calls or conditional branches inside the loop. These loops
-compile in a streamlined way that uses relatively few instructions and
-finishes each instruction in fewer clock cycles, on average, by
-effectively using the processor pipeline and cache memory.
-
-The result of benchmark shows 2x~4x speedup in our typical queries.
-
-5. Backup and Recovery
-----------------------
-
-Data backup function is provided to enhance data security. The minimum
-granularity of backup and recovery is partition. Users can develop
-plugins to backup data to any specified remote storage. The backup data
-can always be recovered to Doris at all time, to achieve the data
-rollback purpose.
-
-Currently we only support full data backup data rather than incremental
-backups for the following reasons:
-
-1. Remote storage system is beyond the control of the Doris system. We
- cannot guarantee whether the data has been changed between two backup
- operations. And data verification operations always come at a high
- price.
-
-2. We support data backup on partition granularity. And majority of
- applications are time series applications. By dividing data using
- time column, it has been able to meet the needs of the vast majority
- of incremental backup in chronological order.
-
-In addition to improving data security, the backup function also
-provides a way to export the data. Data can be exported to other
-downstream systems for further processing.
-
-.. toctree::
- :hidden:
-
- documentation/cn/index
- documentation/en/index
diff --git a/docs/zh-CN/README.md b/docs/zh-CN/README.md
new file mode 100644
index 00000000000000..4910446048731a
--- /dev/null
+++ b/docs/zh-CN/README.md
@@ -0,0 +1,8 @@
+---
+home: true
+heroImage: /images/doris-logo.png
+heroText: Apache Doris
+tagline: 基于 MPP 的交互式 SQL 数据仓库,主要用于解决报表和多维分析。
+actionText: 快速上手 →
+actionLink: /zh-CN/installing/compilation
+---
diff --git a/docs/zh-CN/administrator-guide/alter-table/alter-table-bitmap-index.md b/docs/zh-CN/administrator-guide/alter-table/alter-table-bitmap-index.md
new file mode 100644
index 00000000000000..0a768a99716e80
--- /dev/null
+++ b/docs/zh-CN/administrator-guide/alter-table/alter-table-bitmap-index.md
@@ -0,0 +1,86 @@
+---
+{
+ "title": "Bitmap 索引",
+ "language": "zh-CN"
+}
+---
+
+
+
+# Bitmap 索引
+用户可以通过创建bitmap index 加速查询
+本文档主要介绍如何创建 index 作业,以及创建 index 的一些注意事项和常见问题。
+
+## 名词解释
+* bitmap index:位图索引,是一种快速数据结构,能够加快查询速度
+
+## 原理介绍
+创建和删除本质上是一个 schema change 的作业,具体细节可以参照 [Schema Change](alter-table-schema-change)。
+
+## 语法
+index 创建和修改相关语法有两种形式,一种集成与 alter table 语句中,另一种是使用单独的
+create/drop index 语法
+1. 创建索引
+
+ 创建索引的的语法可以参见 [CREATE INDEX](../../sql-reference/sql-statements/Data%20Definition/CREATE%20INDEX.html)
+ 或 [ALTER TABLE](../../sql-reference/sql-statements/Data%20Definition/ALTER%20TABLE.html) 中bitmap 索引相关的操作,
+ 也可以通过在创建表时指定bitmap 索引,参见[CREATE TABLE](../../sql-reference/sql-statements/Data%20Definition/CREATE%20TABLE.html)
+
+2. 查看索引
+
+ 参照[SHOW INDEX](../../sql-reference/sql-statements/Administration/SHOW%20INDEX.html)
+
+3. 删除索引
+
+ 参照[DROP INDEX](../../sql-reference/sql-statements/Data%20Definition/DROP%20INDEX.html)
+ 或者 [ALTER TABLE](../../sql-reference/sql-statements/Data%20Definition/ALTER%20TABLE.html) 中bitmap 索引相关的操作
+
+## 创建作业
+参照 schema change 文档 [Scheam Change](alter-table-schema-change.html)
+
+## 查看作业
+参照 schema change 文档 [Scheam Change](alter-table-schema-change.html)
+
+## 取消作业
+参照 schema change 文档 [Scheam Change](alter-table-schema-change.html)
+
+## 注意事项
+* 目前索引仅支持 bitmap 类型的索引。
+* bitmap 索引仅在单列上创建。
+* bitmap 索引能够应用在 `Duplicate` 数据模型的所有列和 `Aggregate`, `Uniq` 模型的key列上。
+* bitmap 索引支持的数据类型如下:
+ * `TINYINT`
+ * `SMALLINT`
+ * `INT`
+ * `UNSIGNEDINT`
+ * `BIGINT`
+ * `CHAR`
+ * `VARCHAE`
+ * `DATE`
+ * `DATETIME`
+ * `LARGEINT`
+ * `DECIMAL`
+ * `BOOL`
+
+* bitmap索引仅在 segmentV2 下生效,需要在be的配置文件中增加如下配置
+
+ ```
+ default_rowset_type=BETA
+ ```
diff --git a/docs/zh-CN/administrator-guide/alter-table/alter-table-rollup.md b/docs/zh-CN/administrator-guide/alter-table/alter-table-rollup.md
new file mode 100644
index 00000000000000..7d571a2d8a6998
--- /dev/null
+++ b/docs/zh-CN/administrator-guide/alter-table/alter-table-rollup.md
@@ -0,0 +1,194 @@
+---
+{
+ "title": "Rollup",
+ "language": "zh-CN"
+}
+---
+
+
+
+# Rollup
+
+用户可以通过创建上卷表(Rollup)加速查询。关于 Rollup 的概念和使用方式可以参阅 [数据模型、ROLLUP 及前缀索引](../../getting-started/data-model-rollup.md) 和 [Rollup 与查询](../../getting-started/hit-the-rollup.md) 两篇文档。
+
+本文档主要介绍如何创建 Rollup 作业,以及创建 Rollup 的一些注意事项和常见问题。
+
+## 名词解释
+
+* Base Table:基表。每一个表被创建时,都对应一个基表。基表存储了这个表的完整的数据。Rollup 通常基于基表中的数据创建(也可以通过其他 Rollup 创建)。
+* Index:物化索引。Rollup 或 Base Table 都被称为物化索引。
+* Transaction:事务。每一个导入任务都是一个事务,每个事务有一个唯一递增的 Transaction ID。
+
+## 原理介绍
+
+创建 Rollup 的基本过程,是通过 Base 表的数据,生成一份新的包含指定列的 Rollup 的数据。其中主要需要进行两部分数据转换,一是已存在的历史数据的转换,二是在 Rollup 执行过程中,新到达的导入数据的转换。
+
+```
++----------+
+| Load Job |
++----+-----+
+ |
+ | Load job generates both base and rollup index data
+ |
+ | +------------------+ +---------------+
+ | | Base Index | | Base Index |
+ +------> New Incoming Data| | History Data |
+ | +------------------+ +------+--------+
+ | |
+ | | Convert history data
+ | |
+ | +------------------+ +------v--------+
+ | | Rollup Index | | Rollup Index |
+ +------> New Incoming Data| | History Data |
+ +------------------+ +---------------+
+```
+
+在开始转换历史数据之前,Doris 会获取一个最新的 Transaction ID。并等待这个 Transaction ID 之前的所有导入事务完成。这个 Transaction ID 成为分水岭。意思是,Doris 保证在分水岭之后的所有导入任务,都会同时为 Rollup Index 生成数据。这样当历史数据转换完成后,可以保证 Rollup 和 Base 表的数据是齐平的。
+
+## 创建作业
+
+创建 Rollup 的具体语法可以查看帮助 `HELP ALTER TABLE` 中 Rollup 部分的说明。
+
+Rollup 的创建是一个异步过程,作业提交成功后,用户需要通过 `SHOW ALTER TABLE ROLLUP` 命令来查看作业进度。
+
+## 查看作业
+
+`SHOW ALTER TABLE ROLLUP` 可以查看当前正在执行或已经完成的 Rollup 作业。举例如下:
+
+```
+ JobId: 20037
+ TableName: tbl1
+ CreateTime: 2019-08-06 15:38:49
+ FinishedTime: N/A
+ BaseIndexName: tbl1
+RollupIndexName: r1
+ RollupId: 20038
+ TransactionId: 10034
+ State: PENDING
+ Msg:
+ Progress: N/A
+ Timeout: 86400
+```
+
+* JobId:每个 Rollup 作业的唯一 ID。
+* TableName:Rollup 对应的基表的表名。
+* CreateTime:作业创建时间。
+* FinishedTime:作业结束时间。如未结束,则显示 "N/A"。
+* BaseIndexName:Rollup 对应的源 Index 的名称。
+* RollupIndexName:Rollup 的名称。
+* RollupId:Rollup 的唯一 ID。
+* TransactionId:转换历史数据的分水岭 transaction ID。
+* State:作业所在阶段。
+ * PENDING:作业在队列中等待被调度。
+ * WAITING_TXN:等待分水岭 transaction ID 之前的导入任务完成。
+ * RUNNING:历史数据转换中。
+ * FINISHED:作业成功。
+ * CANCELLED:作业失败。
+* Msg:如果作业失败,这里会显示失败信息。
+* Progress:作业进度。只有在 RUNNING 状态才会显示进度。进度是以 M/N 的形式显示。其中 N 为 Rollup 的总副本数。M 为已完成历史数据转换的副本数。
+* Timeout:作业超时时间。单位秒。
+
+## 取消作业
+
+在作业状态不为 FINISHED 或 CANCELLED 的情况下,可以通过以下命令取消 Rollup 作业:
+
+`CANCEL ALTER TABLE ROLLUP FROM tbl_name;`
+
+## 注意事项
+
+* 一张表在同一时间只能有一个 Rollup 作业在运行。且一个作业中只能创建一个 Rollup。
+
+* Rollup 操作不阻塞导入和查询操作。
+
+* 如果 DELETE 操作,where 条件中的某个 Key 列在某个 Rollup 中不存在,则不允许该 DELETE。
+
+ 如果某个 Key 列在某一 Rollup 中不存在,则 DELETE 操作无法对该 Rollup 进行数据删除,从而无法保证 Rollup 表和 Base 表的数据一致性。
+
+* Rollup 的列必须存在于 Base 表中。
+
+ Rollup 的列永远是 Base 表列的子集。不能出现 Base 表中不存在的列。
+
+* 如果 Rollup 中包含 REPLACE 聚合类型的列,则该 Rollup 必须包含所有 Key 列。
+
+ 假设 Base 表结构如下:
+
+ ```(k1 INT, k2 INT, v1 INT REPLACE, v2 INT SUM)```
+
+ 如果需要创建的 Rollup 包含 `v1` 列,则必须包含 `k1`, `k2` 列。否则系统无法决定 `v1` 列在 Rollup 中的取值。
+
+ 注意,Unique 数据模型表中的所有 Value 列都是 REPLACE 聚合类型。
+
+* DUPLICATE 数据模型表的 Rollup,可以指定 Rollup 的 DUPLICATE KEY。
+
+ DUPLICATE 数据模型表中的 DUPLICATE KEY 其实就是排序列。Rollup 可以指定自己的排序列,但排序列必须是 Rollup 列顺序的前缀。如果不指定,则系统会检查 Rollup 是否包含了 Base 表的所有排序列,如果没有包含,则会报错。举例:
+
+ Base 表结构:`(k1 INT, k2 INT, k3 INT) DUPLICATE KEY(k1, k2)`
+
+ 则 Rollup 可以为:`(k2 INT, k1 INT) DUPLICATE KEY(k2)`
+
+* Rollup 不需要包含 Base 表的分区列或分桶列。
+
+## 常见问题
+
+* 一个表可以创建多少 Rollup
+
+ 一个表能够创建的 Rollup 个数理论上没有限制,但是过多的 Rollup 会影响导入性能。因为导入时,会同时给所有 Rollup 产生数据。同时 Rollup 会占用物理存储空间。通常一个表的 Rollup 数量在 10 个以内比较合适。
+
+* Rollup 创建的速度
+
+ 目前 Rollup 创建速度按照最差效率估计约为 10MB/s。保守起见,用户可以根据这个速率来设置作业的超时时间。
+
+* 提交作业报错 `Table xxx is not stable. ...`
+
+ Rollup 只有在表数据完整且非均衡状态下才可以开始。如果表的某些数据分片副本不完整,或者某些副本正在进行均衡操作,则提交会被拒绝。
+
+ 数据分片副本是否完整,可以通过以下命令查看:
+
+ ```ADMIN SHOW REPLICA STATUS FROM tbl WHERE STATUS != "OK";```
+
+ 如果有返回结果,则说明有副本有问题。通常系统会自动修复这些问题,用户也可以通过以下命令优先修复这个表:
+
+ ```ADMIN REPAIR TABLE tbl1;```
+
+ 用户可以通过以下命令查看是否有正在运行的均衡任务:
+
+ ```SHOW PROC "/cluster_balance/pending_tablets";```
+
+ 可以等待均衡任务完成,或者通过以下命令临时禁止均衡操作:
+
+ ```ADMIN SET FRONTEND CONFIG ("disable_balance" = "true");```
+
+## 相关配置
+
+### FE 配置
+
+* `alter_table_timeout_second`:作业默认超时时间,86400 秒。
+
+### BE 配置
+
+* `alter_tablet_worker_count`:在 BE 端用于执行历史数据转换的线程数。默认为 3。如果希望加快 Rollup 作业的速度,可以适当调大这个参数后重启 BE。但过多的转换线程可能会导致 IO 压力增加,影响其他操作。该线程和 Schema Change 作业共用。
+
+
+
+
+
+
+
+
diff --git a/docs/zh-CN/administrator-guide/alter-table/alter-table-schema-change.md b/docs/zh-CN/administrator-guide/alter-table/alter-table-schema-change.md
new file mode 100644
index 00000000000000..6ab14cc7642c92
--- /dev/null
+++ b/docs/zh-CN/administrator-guide/alter-table/alter-table-schema-change.md
@@ -0,0 +1,249 @@
+---
+{
+ "title": "Schema Change",
+ "language": "zh-CN"
+}
+---
+
+
+
+# Schema Change
+
+用户可以通过 Schema Change 操作来修改已存在表的 Schema。目前 Doris 支持以下几种修改:
+
+* 增加、删除列
+* 修改列类型
+* 调整列顺序
+* 增加、修改 Bloom Filter
+* 增加、删除 bitmap index
+
+本文档主要介绍如何创建 Schema Change 作业,以及进行 Schema Change 的一些注意事项和常见问题。
+
+## 名词解释
+
+* Base Table:基表。每一个表被创建时,都对应一个基表。
+* Rollup:基于基表或者其他 Rollup 创建出来的上卷表。
+* Index:物化索引。Rollup 或 Base Table 都被称为物化索引。
+* Transaction:事务。每一个导入任务都是一个事务,每个事务有一个唯一递增的 Transaction ID。
+
+## 原理介绍
+
+执行 Schema Change 的基本过程,是通过原 Index 的数据,生成一份新 Schema 的 Index 的数据。其中主要需要进行两部分数据转换,一是已存在的历史数据的转换,二是在 Schema Change 执行过程中,新到达的导入数据的转换。
+
+```
++----------+
+| Load Job |
++----+-----+
+ |
+ | Load job generates both origin and new index data
+ |
+ | +------------------+ +---------------+
+ | | Origin Index | | Origin Index |
+ +------> New Incoming Data| | History Data |
+ | +------------------+ +------+--------+
+ | |
+ | | Convert history data
+ | |
+ | +------------------+ +------v--------+
+ | | New Index | | New Index |
+ +------> New Incoming Data| | History Data |
+ +------------------+ +---------------+
+```
+
+在开始转换历史数据之前,Doris 会获取一个最新的 Transaction ID。并等待这个 Transaction ID 之前的所有导入事务完成。这个 Transaction ID 成为分水岭。意思是,Doris 保证在分水岭之后的所有导入任务,都会同时为原 Index 和新 Index 生成数据。这样当历史数据转换完成后,可以保证新的 Index 中的数据是完整的。
+
+## 创建作业
+
+创建 Schema Change 的具体语法可以查看帮助 `HELP ALTER TABLE` 中 Schema Change 部分的说明。
+
+Schema Change 的创建是一个异步过程,作业提交成功后,用户需要通过 `SHOW ALTER TABLE COLUMN` 命令来查看作业进度。
+
+## 查看作业
+
+`SHOW ALTER TABLE COLUMN` 可以查看当前正在执行或已经完成的 Schema Change 作业。当一次 Schema Change 作业涉及到多个 Index 时,该命令会显示多行,每行对应一个 Index。举例如下:
+
+```
+ JobId: 20021
+ TableName: tbl1
+ CreateTime: 2019-08-05 23:03:13
+ FinishTime: 2019-08-05 23:03:42
+ IndexName: tbl1
+ IndexId: 20022
+OriginIndexId: 20017
+SchemaVersion: 2:792557838
+TransactionId: 10023
+ State: FINISHED
+ Msg:
+ Progress: N/A
+ Timeout: 86400
+```
+
+* JobId:每个 Schema Change 作业的唯一 ID。
+* TableName:Schema Change 对应的基表的表名。
+* CreateTime:作业创建时间。
+* FinishedTime:作业结束时间。如未结束,则显示 "N/A"。
+* IndexName: 本次修改所涉及的某一个 Index 的名称。
+* IndexId:新的 Index 的唯一 ID。
+* OriginIndexId:旧的 Index 的唯一 ID。
+* SchemaVersion:以 M:N 的格式展示。其中 M 表示本次 Schema Change 变更的版本,N 表示对应的 Hash 值。每次 Schema Change,版本都会递增。
+* TransactionId:转换历史数据的分水岭 transaction ID。
+* State:作业所在阶段。
+ * PENDING:作业在队列中等待被调度。
+ * WAITING_TXN:等待分水岭 transaction ID 之前的导入任务完成。
+ * RUNNING:历史数据转换中。
+ * FINISHED:作业成功。
+ * CANCELLED:作业失败。
+* Msg:如果作业失败,这里会显示失败信息。
+* Progress:作业进度。只有在 RUNNING 状态才会显示进度。进度是以 M/N 的形式显示。其中 N 为 Schema Change 涉及的总副本数。M 为已完成历史数据转换的副本数。
+* Timeout:作业超时时间。单位秒。
+
+## 取消作业
+
+在作业状态不为 FINISHED 或 CANCELLED 的情况下,可以通过以下命令取消 Schema Change 作业:
+
+`CANCEL ALTER TABLE COLUMN FROM tbl_name;`
+
+## 最佳实践
+
+Schema Change 可以在一个作业中,对多个 Index 进行不同的修改。举例如下:
+
+源 Schema:
+
+```
++-----------+-------+------+------+------+---------+-------+
+| IndexName | Field | Type | Null | Key | Default | Extra |
++-----------+-------+------+------+------+---------+-------+
+| tbl1 | k1 | INT | No | true | N/A | |
+| | k2 | INT | No | true | N/A | |
+| | k3 | INT | No | true | N/A | |
+| | | | | | | |
+| rollup2 | k2 | INT | No | true | N/A | |
+| | | | | | | |
+| rollup1 | k1 | INT | No | true | N/A | |
+| | k2 | INT | No | true | N/A | |
++-----------+-------+------+------+------+---------+-------+
+```
+
+可以通过以下命令给 rollup1 和 rollup2 都加入一列 k4,并且再给 rollup2 加入一列 k5:
+
+```
+ALTER TABLE tbl1
+ADD COLUMN k4 INT default "1" to rollup1,
+ADD COLUMN k4 INT default "1" to rollup2,
+ADD COLUMN k5 INT default "1" to rollup2;
+```
+
+完成后,Schema 变为:
+
+```
++-----------+-------+------+------+------+---------+-------+
+| IndexName | Field | Type | Null | Key | Default | Extra |
++-----------+-------+------+------+------+---------+-------+
+| tbl1 | k1 | INT | No | true | N/A | |
+| | k2 | INT | No | true | N/A | |
+| | k3 | INT | No | true | N/A | |
+| | k4 | INT | No | true | 1 | |
+| | k5 | INT | No | true | 1 | |
+| | | | | | | |
+| rollup2 | k2 | INT | No | true | N/A | |
+| | k4 | INT | No | true | 1 | |
+| | k5 | INT | No | true | 1 | |
+| | | | | | | |
+| rollup1 | k1 | INT | No | true | N/A | |
+| | k2 | INT | No | true | N/A | |
+| | k4 | INT | No | true | 1 | |
++-----------+-------+------+------+------+---------+-------+
+```
+
+可以看到,Base 表 tbl1 也自动加入了 k4, k5 列。即给任意 rollup 增加的列,都会自动加入到 Base 表中。
+
+同时,不允许向 Rollup 中加入 Base 表已经存在的列。如果用户需要这样做,可以重新建立一个包含新增列的 Rollup,之后再删除原 Rollup。
+
+## 注意事项
+
+* 一张表在同一时间只能有一个 Schema Change 作业在运行。
+
+* Schema Change 操作不阻塞导入和查询操作。
+
+* 分区列和分桶列不能修改。
+
+* 如果 Schema 中有 REPLACE 方式聚合的 value 列,则不允许删除 Key 列。
+
+ 如果删除 Key 列,Doris 无法决定 REPLACE 列的取值。
+
+ Unique 数据模型表的所有非 Key 列都是 REPLACE 聚合方式。
+
+* 在新增聚合类型为 SUM 或者 REPLACE 的 value 列时,该列的默认值对历史数据没有含义。
+
+ 因为历史数据已经失去明细信息,所以默认值的取值并不能实际反映聚合后的取值。
+
+* 当修改列类型时,除 Type 以外的字段都需要按原列上的信息补全。
+
+ 如修改列 `k1 INT SUM NULL DEFAULT "1"` 类型为 BIGINT,则需执行命令如下:
+
+ ```ALTER TABLE tbl1 MODIFY COLUMN `k1` BIGINT SUM NULL DEFAULT "1";```
+
+ 注意,除新的列类型外,如聚合方式,Nullable 属性,以及默认值都要按照原信息补全。
+
+* 不支持修改列名称、聚合类型、Nullable 属性、默认值以及列注释。
+
+## 常见问题
+
+* Schema Change 的执行速度
+
+ 目前 Schema Change 执行速度按照最差效率估计约为 10MB/s。保守起见,用户可以根据这个速率来设置作业的超时时间。
+
+* 提交作业报错 `Table xxx is not stable. ...`
+
+ Schema Change 只有在表数据完整且非均衡状态下才可以开始。如果表的某些数据分片副本不完整,或者某些副本正在进行均衡操作,则提交会被拒绝。
+
+ 数据分片副本是否完整,可以通过以下命令查看:
+
+ ```ADMIN SHOW REPLICA STATUS FROM tbl WHERE STATUS != "OK";```
+
+ 如果有返回结果,则说明有副本有问题。通常系统会自动修复这些问题,用户也可以通过以下命令优先修复这个表:
+
+ ```ADMIN REPAIR TABLE tbl1;```
+
+ 用户可以通过以下命令查看是否有正在运行的均衡任务:
+
+ ```SHOW PROC "/cluster_balance/pending_tablets";```
+
+ 可以等待均衡任务完成,或者通过以下命令临时禁止均衡操作:
+
+ ```ADMIN SET FRONTEND CONFIG ("disable_balance" = "true");```
+
+## 相关配置
+
+### FE 配置
+
+* `alter_table_timeout_second`:作业默认超时时间,86400 秒。
+
+### BE 配置
+
+* `alter_tablet_worker_count`:在 BE 端用于执行历史数据转换的线程数。默认为 3。如果希望加快 Schema Change 作业的速度,可以适当调大这个参数后重启 BE。但过多的转换线程可能会导致 IO 压力增加,影响其他操作。该线程和 Rollup 作业共用。
+
+
+
+
+
+
+
+
diff --git a/docs/zh-CN/administrator-guide/alter-table/alter-table-temp-partition.md b/docs/zh-CN/administrator-guide/alter-table/alter-table-temp-partition.md
new file mode 100644
index 00000000000000..32b328f6a4e407
--- /dev/null
+++ b/docs/zh-CN/administrator-guide/alter-table/alter-table-temp-partition.md
@@ -0,0 +1,251 @@
+---
+{
+ "title": "临时分区",
+ "language": "zh-CN"
+}
+---
+
+
+
+# 临时分区
+
+在 0.12 版本中,Doris 支持了临时分区功能。
+
+临时分区是归属于某一分区表的。只有分区表可以创建临时分区。
+
+## 规则
+
+* 临时分区的分区列和正式分区相同,且不可修改。
+* 一张表所有临时分区之间的分区范围不可重叠,但临时分区的范围和正式分区范围可以重叠。
+* 临时分区的分区名称不能和正式分区以及其他临时分区重复。
+
+## 支持的操作
+
+临时分区支持添加、删除、替换操作。
+
+### 添加临时分区
+
+可以通过 `ALTER TABLE ADD TEMPORARY PARTITION` 语句对一个表添加临时分区:
+
+```
+ALTER TABLE tbl1 ADD TEMPORARY PARTITION tp1 VALUES LESS THAN("2020-02-01");
+
+ALTER TABLE tbl2 ADD TEMPORARY PARTITION tp1 VALUES [("2020-01-01"), ("2020-02-01"));
+
+ALTER TABLE tbl1 ADD TEMPORARY PARTITION tp1 VALUES LESS THAN("2020-02-01")
+("in_memory" = "true", "replication_num" = "1")
+DISTRIBUTED BY HASH(k1) BUCKETS 5;
+```
+
+通过 `HELP ALTER TABLE;` 查看更多帮助和示例。
+
+添加操作的一些说明:
+
+* 临时分区的添加和正式分区的添加操作相似。临时分区的分区范围独立于正式分区。
+* 临时分区可以独立指定一些属性。包括分桶数、副本数、是否是内存表、存储介质等信息。
+
+### 删除临时分区
+
+可以通过 `ALTER TABLE DROP TEMPORARY PARTITION` 语句删除一个表的临时分区:
+
+```
+ALTER TABLE tbl1 DROP TEMPORARY PARTITION tp1;
+```
+
+通过 `HELP ALTER TABLE;` 查看更多帮助和示例。
+
+删除操作的一些说明:
+
+* 删除临时分区,不影响正式分区的数据。
+
+### 替换分区
+
+可以通过 `ALTER TABLE REPLACE PARTITION` 语句将一个表的正式分区替换为临时分区。
+
+```
+ALTER TABLE tbl1 REPLACE PARTITION (p1) WITH TEMPORARY PARTITION (tp1);
+
+ALTER TABLE tbl1 REPLACE PARTITION (p1, p2) WITH TEMPORARY PARTITION (tp1, tp2, tp3);
+
+ALTER TABLE tbl1 REPLACE PARTITION (p1, p2) WITH TEMPORARY PARTITION (tp1, tp2)
+PROPERTIES (
+ "strict_range" = "false",
+ "use_temp_partition_name" = "true"
+);
+```
+
+通过 `HELP ALTER TABLE;` 查看更多帮助和示例。
+
+替换操作有两个特殊的可选参数:
+
+1. `strict_range`
+
+ 默认为 true。当该参数为 true 时,表示要被替换的所有正式分区的范围并集需要和替换的临时分区的范围并集完全相同。当置为 false 时,只需要保证替换后,新的正式分区间的范围不重叠即可。下面举例说明:
+
+ * 示例1
+
+ 待替换的分区 p1, p2, p3 的范围 (=> 并集):
+
+ ```
+ [10, 20), [20, 30), [40, 50) => [10, 30), [40, 50)
+ ```
+
+ 替换分区 tp1, tp2 的范围(=> 并集):
+
+ ```
+ [10, 30), [40, 45), [45, 50) => [10, 30), [40, 50)
+ ```
+
+ 范围并集相同,则可以使用 tp1 和 tp2 替换 p1, p2, p3。
+
+ * 示例2
+
+ 待替换的分区 p1 的范围 (=> 并集):
+
+ ```
+ [10, 50) => [10, 50)
+ ```
+
+ 替换分区 tp1, tp2 的范围(=> 并集):
+
+ ```
+ [10, 30), [40, 50) => [10, 30), [40, 50)
+ ```
+
+ 范围并集不相同,如果 `strict_range` 为 true,则不可以使用 tp1 和 tp2 替换 p1。如果为 false,且替换后的两个分区范围 `[10, 30), [40, 50)` 和其他正式分区不重叠,则可以替换。
+
+2. `use_temp_partition_name`
+
+ 默认为 false。当该参数为 false,并且待替换的分区和替换分区的个数相同时,则替换后的正式分区名称维持不变。如果为 true,则替换后,正式分区的名称为替换分区的名称。下面举例说明:
+
+ * 示例1
+
+ ```
+ ALTER TABLE tbl1 REPLACE PARTITION (p1) WITH TEMPORARY PARTITION (tp1);
+ ```
+
+ `use_temp_partition_name` 默认为 false,则在替换后,分区的名称依然为 p1,但是相关的数据和属性都替换为 tp1 的。
+
+ 如果 `use_temp_partition_name` 默认为 true,则在替换后,分区的名称为 tp1。p1 分区不再存在。
+
+ * 示例2
+
+ ```
+ ALTER TABLE tbl1 REPLACE PARTITION (p1, p2) WITH TEMPORARY PARTITION (tp1);
+ ```
+
+ `use_temp_partition_name` 默认为 false,但因为待替换分区的个数和替换分区的个数不同,则该参数无效。替换后,分区名称为 tp1,p1 和 p2 不再存在。
+
+替换操作的一些说明:
+
+* 分区替换成功后,被替换的分区将被删除且不可恢复。
+
+## 临时分区的导入和查询
+
+用户可以将数据导入到临时分区,也可以指定临时分区进行查询。
+
+1. 导入临时分区
+
+ 根据导入方式的不同,指定导入临时分区的语法稍有差别。这里通过示例进行简单说明
+
+ ```
+ INSERT INTO tbl TEMPORARY PARTITION(tp1, tp2, ...) SELECT ....
+ ```
+
+ ```
+ curl --location-trusted -u root: -H "label:123" -H "temporary_partitions: tp1, tp2, ..." -T testData http://host:port/api/testDb/testTbl/_stream_load
+ ```
+
+ ```
+ LOAD LABEL example_db.label1
+ (
+ DATA INFILE("hdfs://hdfs_host:hdfs_port/user/palo/data/input/file")
+ INTO TABLE `my_table`
+ TEMPORARY PARTITION (tp1, tp2, ...)
+ ...
+ )
+ WITH BROKER hdfs ("username"="hdfs_user", "password"="hdfs_password");
+ ```
+
+ ```
+ CREATE ROUTINE LOAD example_db.test1 ON example_tbl
+ COLUMNS(k1, k2, k3, v1, v2, v3 = k1 * 100),
+ TEMPORARY PARTITIONS(tp1, tp2, ...),
+ WHERE k1 > 100
+ PROPERTIES
+ (...)
+ FROM KAFKA
+ (...);
+ ```
+
+2. 查询临时分区
+
+ ```
+ SELECT ... FROM
+ tbl1 TEMPORARY PARTITION(tp1, tp2, ...)
+ JOIN
+ tbl2 TEMPORARY PARTITION(tp1, tp2, ...)
+ ON ...
+ WHERE ...;
+ ```
+
+## 和其他操作的关系
+
+### DROP
+
+* 使用 Drop 操作直接删除数据库或表后,可以通过 Recover 命令恢复数据库或表(限定时间内),但临时分区不会被恢复。
+* 使用 Alter 命令删除正式分区后,可以通过 Recover 命令恢复分区(限定时间内)。操作正式分区和临时分区无关。
+* 使用 Alter 命令删除临时分区后,无法通过 Recover 命令恢复临时分区。
+
+### TRUNCATE
+
+* 使用 Truncate 命令清空表,表的临时分区会被删除,且不可恢复。
+* 使用 Truncate 命令清空正式分区时,不影响临时分区。
+* 不可使用 Truncate 命令清空临时分区。
+
+### ALTER
+
+* 当表存在临时分区时,无法使用 Alter 命令对表进行 Schema Change、Rollup 等变更操作。
+* 当表在进行变更操作时,无法对表添加临时分区。
+
+
+## 最佳实践
+
+1. 原子的覆盖写操作
+
+ 某些情况下,用户希望能够重写某一分区的数据,但如果采用先删除再导入的方式进行,在中间会有一段时间无法查看数据。这是,用户可以先创建一个对应的临时分区,将新的数据导入到临时分区后,通过替换操作,原子的替换原有分区,以达到目的。
+
+2. 修改分桶数
+
+ 某些情况下,用户在创建分区时使用了不合适的分桶数。则用户可以先创建一个对应分区范围的临时分区,并指定新的分桶数。然后通过 `INSERT INTO` 命令将正式分区的数据导入到临时分区中,通过替换操作,原子的替换原有分区,以达到目的。
+
+3. 合并或分割分区
+
+ 某些情况下,用户希望对分区的范围进行修改,比如合并两个分区,或将一个大分区分割成多个小分区。则用户可以先建立对应合并或分割后范围的临时分区,然后通过 `INSERT INTO` 命令将正式分区的数据导入到临时分区中,通过替换操作,原子的替换原有分区,以达到目的。
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/zh-CN/administrator-guide/backup-restore.md b/docs/zh-CN/administrator-guide/backup-restore.md
new file mode 100644
index 00000000000000..2102e772dbc76f
--- /dev/null
+++ b/docs/zh-CN/administrator-guide/backup-restore.md
@@ -0,0 +1,186 @@
+---
+{
+ "title": "备份与恢复",
+ "language": "zh-CN"
+}
+---
+
+
+
+# 备份与恢复
+
+Doris 支持将当前数据以文件的形式,通过 broker 备份到远端存储系统中。之后可以通过 恢复 命令,从远端存储系统中将数据恢复到任意 Doris 集群。通过这个功能,Doris 可以支持将数据定期的进行快照备份。也可以通过这个功能,在不同集群间进行数据迁移。
+
+该功能需要 Doris 版本 0.8.2+
+
+使用该功能,需要部署对应远端存储的 broker。如 BOS、HDFS 等。可以通过 `SHOW BROKER;` 查看当前部署的 broker。
+
+## 简要原理说明
+
+### 备份(Backup)
+
+备份操作是将指定表或分区的数据,直接以 Doris 存储的文件的形式,上传到远端仓库中进行存储。当用户提交 Backup 请求后,系统内部会做如下操作:
+
+1. 快照及快照上传
+
+ 快照阶段会对指定的表或分区数据文件进行快照。之后,备份都是对快照进行操作。在快照之后,对表进行的更改、导入等操作都不再影响备份的结果。快照只是对当前数据文件产生一个硬链,耗时很少。快照完成后,会开始对这些快照文件进行逐一上传。快照上传由各个 Backend 并发完成。
+
+2. 元数据准备及上传
+
+ 数据文件快照上传完成后,Frontend 会首先将对应元数据写成本地文件,然后通过 broker 将本地元数据文件上传到远端仓库。完成最终备份作业。
+
+### 恢复(Restore)
+
+恢复操作需要指定一个远端仓库中已存在的备份,然后将这个备份的内容恢复到本地集群中。当用户提交 Restore 请求后,系统内部会做如下操作:
+
+1. 在本地创建对应的元数据
+
+ 这一步首先会在本地集群中,创建恢复对应的表分区等结构。创建完成后,该表可见,但是不可访问。
+
+2. 本地snapshot
+
+ 这一步是将上一步创建的表做一个快照。这其实是一个空快照(因为刚创建的表是没有数据的),其目的主要是在 Backend 上产生对应的快照目录,用于之后接收从远端仓库下载的快照文件。
+
+3. 下载快照
+
+ 远端仓库中的快照文件,会被下载到对应的上一步生成的快照目录中。这一步由各个 Backend 并发完成。
+
+4. 生效快照
+
+ 快照下载完成后,我们要将各个快照映射为当前本地表的元数据。然后重新加载这些快照,使之生效,完成最终的恢复作业。
+
+## 最佳实践
+
+### 备份
+
+当前我们支持最小分区(Partition)粒度的全量备份(增量备份有可能在未来版本支持)。如果需要对数据进行定期备份,首先需要在建表时,合理的规划表的分区及分桶,比如按时间进行分区。然后在之后的运行过程中,按照分区粒度进行定期的数据备份。
+
+### 数据迁移
+
+用户可以先将数据备份到远端仓库,再通过远端仓库将数据恢复到另一个集群,完成数据迁移。因为数据备份是通过快照的形式完成的,所以,在备份作业的快照阶段之后的新的导入数据,是不会备份的。因此,在快照完成后,到恢复作业完成这期间,在原集群上导入的数据,都需要在新集群上同样导入一遍。
+
+建议在迁移完成后,对新旧两个集群并行导入一段时间。完成数据和业务正确性校验后,再将业务迁移到新的集群。
+
+## 重点说明
+
+1. 备份恢复相关的操作目前只允许拥有 ADMIN 权限的用户执行。
+2. 一个 Database 内,只允许有一个正在执行的备份或恢复作业。
+3. 备份和恢复都支持最小分区(Partition)级别的操作,当表的数据量很大时,建议按分区分别执行,以降低失败重试的代价。
+4. 因为备份恢复操作,操作的都是实际的数据文件。所以当一个表的分片过多,或者一个分片有过多的小版本时,可能即使总数据量很小,依然需要备份或恢复很长时间。用户可以通过 `SHOW PARTITIONS FROM table_name;` 和 `SHOW TABLET FROM table_name;` 来查看各个分区的分片数量,以及各个分片的文件版本数量,来预估作业执行时间。文件数量对作业执行的时间影响非常大,所以建议在建表时,合理规划分区分桶,以避免过多的分片。
+5. 当通过 `SHOW BACKUP` 或者 `SHOW RESTORE` 命令查看作业状态时。有可能会在 `TaskErrMsg` 一列中看到错误信息。但只要 `State` 列不为
+ `CANCELLED`,则说明作业依然在继续。这些 Task 有可能会重试成功。当然,有些 Task 错误,也会直接导致作业失败。
+6. 如果恢复作业是一次覆盖操作(指定恢复数据到已经存在的表或分区中),那么从恢复作业的 `COMMIT` 阶段开始,当前集群上被覆盖的数据有可能不能再被还原。此时如果恢复作业失败或被取消,有可能造成之前的数据已损坏且无法访问。这种情况下,只能通过再次执行恢复操作,并等待作业完成。因此,我们建议,如无必要,尽量不要使用覆盖的方式恢复数据,除非确认当前数据已不再使用。
+
+## 相关命令
+
+和备份恢复功能相关的命令如下。以下命令,都可以通过 mysql-client 连接 Doris 后,使用 `help cmd;` 的方式查看详细帮助。
+
+1. CREATE REPOSITORY
+
+ 创建一个远端仓库路径,用于备份或恢复。该命令需要借助 Broker 进程访问远端存储,不同的 Broker 需要提供不同的参数,具体请参阅 [Broker文档](broker.md)
+
+1. BACKUP
+
+ 执行一次备份操作。
+
+3. SHOW BACKUP
+
+ 查看最近一次 backup 作业的执行情况,包括:
+
+ * JobId:本次备份作业的 id。
+ * SnapshotName:用户指定的本次备份作业的名称(Label)。
+ * DbName:备份作业对应的 Database。
+ * State:备份作业当前所在阶段:
+ * PENDING:作业初始状态。
+ * SNAPSHOTING:正在进行快照操作。
+ * UPLOAD_SNAPSHOT:快照结束,准备上传。
+ * UPLOADING:正在上传快照。
+ * SAVE_META:正在本地生成元数据文件。
+ * UPLOAD_INFO:上传元数据文件和本次备份作业的信息。
+ * FINISHED:备份完成。
+ * CANCELLED:备份失败或被取消。
+ * BackupObjs:本次备份涉及的表和分区的清单。
+ * CreateTime:作业创建时间。
+ * SnapshotFinishedTime:快照完成时间。
+ * UploadFinishedTime:快照上传完成时间。
+ * FinishedTime:本次作业完成时间。
+ * UnfinishedTasks:在 `SNAPSHOTTING`,`UPLOADING` 等阶段,会有多个子任务在同时进行,这里展示的当前阶段,未完成的子任务的 task id。
+ * TaskErrMsg:如果有子任务执行出错,这里会显示对应子任务的错误信息。
+ * Status:用于记录在整个作业过程中,可能出现的一些状态信息。
+ * Timeout:作业的超时时间,单位是秒。
+
+4. SHOW SNAPSHOT
+
+ 查看远端仓库中已存在的备份。
+
+ * Snapshot:备份时指定的该备份的名称(Label)。
+ * Timestamp:备份的时间戳。
+ * Status:该备份是否正常。
+
+ 如果在 `SHOW SNAPSHOT` 后指定了 where 子句,则可以显示更详细的备份信息。
+
+ * Database:备份时对应的 Database。
+ * Details:展示了该备份完整的数据目录结构。
+
+5. RESTORE
+
+ 执行一次恢复操作。
+
+6. SHOW RESTORE
+
+ 查看最近一次 restore 作业的执行情况,包括:
+
+ * JobId:本次恢复作业的 id。
+ * Label:用户指定的仓库中备份的名称(Label)。
+ * Timestamp:用户指定的仓库中备份的时间戳。
+ * DbName:恢复作业对应的 Database。
+ * State:恢复作业当前所在阶段:
+ * PENDING:作业初始状态。
+ * SNAPSHOTING:正在进行本地新建表的快照操作。
+ * DOWNLOAD:正在发送下载快照任务。
+ * DOWNLOADING:快照正在下载。
+ * COMMIT:准备生效已下载的快照。
+ * COMMITTING:正在生效已下载的快照。
+ * FINISHED:恢复完成。
+ * CANCELLED:恢复失败或被取消。
+ * AllowLoad:恢复期间是否允许导入。
+ * ReplicationNum:恢复指定的副本数。
+ * RestoreObjs:本次恢复涉及的表和分区的清单。
+ * CreateTime:作业创建时间。
+ * MetaPreparedTime:本地元数据生成完成时间。
+ * SnapshotFinishedTime:本地快照完成时间。
+ * DownloadFinishedTime:远端快照下载完成时间。
+ * FinishedTime:本次作业完成时间。
+ * UnfinishedTasks:在 `SNAPSHOTTING`,`DOWNLOADING`, `COMMITTING` 等阶段,会有多个子任务在同时进行,这里展示的当前阶段,未完成的子任务的 task id。
+ * TaskErrMsg:如果有子任务执行出错,这里会显示对应子任务的错误信息。
+ * Status:用于记录在整个作业过程中,可能出现的一些状态信息。
+ * Timeout:作业的超时时间,单位是秒。
+
+7. CANCEL BACKUP
+
+ 取消当前正在执行的备份作业。
+
+8. CANCEL RESTORE
+
+ 取消当前正在执行的恢复作业。
+
+9. DROP REPOSITORY
+
+ 删除已创建的远端仓库。删除仓库,仅仅是删除该仓库在 Doris 中的映射,不会删除实际的仓库数据。
\ No newline at end of file
diff --git a/docs/zh-CN/administrator-guide/broker.md b/docs/zh-CN/administrator-guide/broker.md
new file mode 100644
index 00000000000000..6215a9d1d60da9
--- /dev/null
+++ b/docs/zh-CN/administrator-guide/broker.md
@@ -0,0 +1,287 @@
+---
+{
+ "title": "Broker",
+ "language": "zh-CN"
+}
+---
+
+
+
+# Broker
+
+Broker 是 Doris 集群中一种可选进程,主要用于支持 Doris 读写远端存储上的文件和目录,如 HDFS、BOS 和 AFS 等。
+
+Broker 通过提供一个 RPC 服务端口来提供服务,是一个无状态的 Java 进程,负责为远端存储的读写操作封装一些类 POSIX 的文件操作,如 open,pread,pwrite 等等。除此之外,Broker 不记录任何其他信息,所以包括远端存储的连接信息、文件信息、权限信息等等,都需要通过参数在 RPC 调用中传递给 Broker 进程,才能使得 Broker 能够正确读写文件。
+
+Broker 仅作为一个数据通路,并不参与任何计算,因此仅需占用较少的内存。通常一个 Doris 系统中会部署一个或多个 Broker 进程。并且相同类型的 Broker 会组成一个组,并设定一个 **名称(Broker name)**。
+
+Broker 在 Doris 系统架构中的位置如下:
+
+```
++----+ +----+
+| FE | | BE |
++-^--+ +--^-+
+ | |
+ | |
++-v---------v-+
+| Broker |
++------^------+
+ |
+ |
++------v------+
+|HDFS/BOS/AFS |
++-------------+
+```
+
+本文档主要介绍 Broker 在访问不同远端存储时需要的参数,如连接信息、权限认证信息等等。
+
+## 支持的存储系统
+
+不同的 Broker 类型支持不同的存储系统。
+
+1. 社区版 HDFS
+
+ * 支持简单认证访问
+ * 支持通过 kerberos 认证访问
+ * 支持 HDFS HA 模式访问
+
+2. 百度 HDFS/AFS(开源版本不支持)
+
+ * 支持通过 ugi 简单认证访问
+
+3. 百度对象存储 BOS(开源版本不支持)
+
+ * 支持通过 AK/SK 认证访问
+
+## 需要 Broker 的操作
+
+1. Broker Load
+
+ Broker Load 功能通过 Broker 进程读取远端存储上的文件数据并导入到 Doris 中。示例如下:
+
+ ```
+ LOAD LABEL example_db.label6
+ (
+ DATA INFILE("bos://my_bucket/input/file")
+ INTO TABLE `my_table`
+ )
+ WITH BROKER "broker_name"
+ (
+ "bos_endpoint" = "http://bj.bcebos.com",
+ "bos_accesskey" = "xxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "bos_secret_accesskey" = "yyyyyyyyyyyyyyyyyyyy"
+ )
+ ```
+
+ 其中 `WITH BROKER` 以及之后的 Property Map 用于提供 Broker 相关信息。
+
+2. 数据导出(Export)
+
+ Export 功能通过 Broker 进程,将 Doris 中存储的数据以文本的格式导出到远端存储的文件中。示例如下:
+
+ ```
+ EXPORT TABLE testTbl
+ TO "hdfs://hdfs_host:port/a/b/c"
+ WITH BROKER "broker_name"
+ (
+ "username" = "xxx",
+ "password" = "yyy"
+ );
+ ```
+
+ 其中 `WITH BROKER` 以及之后的 Property Map 用于提供 Broker 相关信息。
+
+3. 创建用于备份恢复的仓库(Create Repository)
+
+ 当用户需要使用备份恢复功能时,需要先通过 `CREATE REPOSITORY` 命令创建一个 “仓库”,仓库元信息中记录了所使用的 Broker 以及相关信息。之后的备份恢复操作,会通过 Broker 将数据备份到这个仓库,或从这个仓库读取数据恢复到 Doris 中。示例如下:
+
+ ```
+ CREATE REPOSITORY `bos_repo`
+ WITH BROKER `broker_name`
+ ON LOCATION "bos://doris_backup"
+ PROPERTIES
+ (
+ "bos_endpoint" = "http://gz.bcebos.com",
+ "bos_accesskey" = "069fc2786e664e63a5f111111114ddbs22",
+ "bos_secret_accesskey" = "70999999999999de274d59eaa980a"
+ );
+ ```
+
+ 其中 `WITH BROKER` 以及之后的 Property Map 用于提供 Broker 相关信息。
+
+
+## Broker 信息
+
+Broker 的信息包括 **名称(Broker name)** 和 **认证信息** 两部分。通常的语法格式如下:
+
+```
+WITH BROKER "broker_name"
+(
+ "username" = "xxx",
+ "password" = "yyy",
+ "other_prop" = "prop_value",
+ ...
+);
+```
+
+### 名称
+
+通常用户需要通过操作命令中的 `WITH BROKER "broker_name"` 子句来指定一个已经存在的 Broker Name。Broker Name 是用户在通过 `ALTER SYSTEM ADD BROKER` 命令添加 Broker 进程时指定的一个名称。一个名称通常对应一个或多个 Broker 进程。Doris 会根据名称选择可用的 Broker 进程。用户可以通过 `SHOW BROKER` 命令查看当前集群中已经存在的 Broker。
+
+**注:Broker Name 只是一个用户自定义名称,不代表 Broker 的类型。**
+
+### 认证信息
+
+不同的 Broker 类型,以及不同的访问方式需要提供不同的认证信息。认证信息通常在 `WITH BROKER "broker_name"` 之后的 Property Map 中以 Key-Value 的方式提供。
+
+#### 社区版 HDFS
+
+1. 简单认证
+
+ 简单认证即 Hadoop 配置 `hadoop.security.authentication` 为 `simple`。
+
+ 使用系统用户访问 HDFS。或者在 Broker 启动的环境变量中添加:```HADOOP_USER_NAME```。
+
+ ```
+ (
+ "username" = "user",
+ "password" = ""
+ );
+ ```
+
+ 密码置空即可。
+
+2. Kerberos 认证
+
+ 该认证方式需提供以下信息:
+
+ * `hadoop.security.authentication`:指定认证方式为 kerberos。
+ * `kerberos_principal`:指定 kerberos 的 principal。
+ * `kerberos_keytab`:指定 kerberos 的 keytab 文件路径。该文件必须为 Broker 进程所在服务器上的文件的绝对路径。并且可以被 Broker 进程访问。
+ * `kerberos_keytab_content`:指定 kerberos 中 keytab 文件内容经过 base64 编码之后的内容。这个跟 `kerberos_keytab` 配置二选一即可。
+
+ 示例如下:
+
+ ```
+ (
+ "hadoop.security.authentication" = "kerberos",
+ "kerberos_principal" = "doris@YOUR.COM",
+ "kerberos_keytab" = "/home/doris/my.keytab"
+ )
+ ```
+ ```
+ (
+ "hadoop.security.authentication" = "kerberos",
+ "kerberos_principal" = "doris@YOUR.COM",
+ "kerberos_keytab_content" = "ASDOWHDLAWIDJHWLDKSALDJSDIWALD"
+ )
+ ```
+ 如果采用Kerberos认证方式,则部署Broker进程的时候需要[krb5.conf](https://web.mit.edu/kerberos/krb5-1.12/doc/admin/conf_files/krb5_conf.html)文件,
+ krb5.conf文件包含Kerberos的配置信息,通常,您应该将krb5.conf文件安装在目录/etc中。您可以通过设置环境变量KRB5_CONFIG覆盖默认位置。
+ krb5.conf文件的内容示例如下:
+ ```
+ [libdefaults]
+ default_realm = DORIS.HADOOP
+ default_tkt_enctypes = des3-hmac-sha1 des-cbc-crc
+ default_tgs_enctypes = des3-hmac-sha1 des-cbc-crc
+ dns_lookup_kdc = true
+ dns_lookup_realm = false
+
+ [realms]
+ DORIS.HADOOP = {
+ kdc = kerberos-doris.hadoop.service:7005
+ }
+ ```
+
+3. HDFS HA 模式
+
+ 这个配置用于访问以 HA 模式部署的 HDFS 集群。
+
+ * `dfs.nameservices`:指定 hdfs 服务的名字,自定义,如:"dfs.nameservices" = "my_ha"。
+ * `dfs.ha.namenodes.xxx`:自定义 namenode 的名字,多个名字以逗号分隔。其中 xxx 为 `dfs.nameservices` 中自定义的名字,如: "dfs.ha.namenodes.my_ha" = "my_nn"。
+ * `dfs.namenode.rpc-address.xxx.nn`:指定 namenode 的rpc地址信息。其中 nn 表示 `dfs.ha.namenodes.xxx` 中配置的 namenode 的名字,如:"dfs.namenode.rpc-address.my_ha.my_nn" = "host:port"。
+ * `dfs.client.failover.proxy.provider`:指定 client 连接 namenode 的 provider,默认为:org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider。
+
+ 示例如下:
+
+ ```
+ (
+ "dfs.nameservices" = "my_ha",
+ "dfs.ha.namenodes.my_ha" = "my_namenode1, my_namenode2",
+ "dfs.namenode.rpc-address.my_ha.my_namenode1" = "nn1_host:rpc_port",
+ "dfs.namenode.rpc-address.my_ha.my_namenode2" = "nn2_host:rpc_port",
+ "dfs.client.failover.proxy.provider" = "org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider"
+ )
+ ```
+
+ HA 模式可以和前面两种认证方式组合,进行集群访问。如通过简单认证访问 HA HDFS:
+
+ ```
+ (
+ "username"="user",
+ "password"="passwd",
+ "dfs.nameservices" = "my_ha",
+ "dfs.ha.namenodes.my_ha" = "my_namenode1, my_namenode2",
+ "dfs.namenode.rpc-address.my_ha.my_namenode1" = "nn1_host:rpc_port",
+ "dfs.namenode.rpc-address.my_ha.my_namenode2" = "nn2_host:rpc_port",
+ "dfs.client.failover.proxy.provider" = "org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider"
+ )
+ ```
+ 关于HDFS集群的配置可以写入hdfs-site.xml文件中,用户使用Broker进程读取HDFS集群的信息时,只需要填写集群的文件路径名和认证信息即可。
+
+#### 百度对象存储 BOS
+
+**(开源版本不支持)**
+
+1. 通过 AK/SK 访问
+
+ * AK/SK:Access Key 和 Secret Key。在百度云安全认证中心可以查看用户的 AK/SK。
+ * Region Endpoint:BOS 所在地区的 Endpoint:
+
+ * 华北-北京:http://bj.bcebos.com
+ * 华北-保定:http://bd.bcebos.com
+ * 华南-广州:http://gz.bcebos.com
+ * 华东-苏州:http://sz.bcebos.com
+
+
+ 示例如下:
+
+ ```
+ (
+ "bos_endpoint" = "http://bj.bcebos.com",
+ "bos_accesskey" = "xxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "bos_secret_accesskey" = "yyyyyyyyyyyyyyyyyyyyyyyyyy"
+ )
+ ```
+
+#### 百度 HDFS/AFS
+
+**(开源版本不支持)**
+
+百度 AFS 和 HDFS 仅支持使用 ugi 的简单认证访问。示例如下:
+
+```
+(
+ "username" = "user",
+ "password" = "passwd"
+);
+```
+
+其中 user 和 passwd 为 Hadoop 的 UGI 配置。
diff --git a/docs/zh-CN/administrator-guide/colocation-join.md b/docs/zh-CN/administrator-guide/colocation-join.md
new file mode 100644
index 00000000000000..c701efd7c7d8b6
--- /dev/null
+++ b/docs/zh-CN/administrator-guide/colocation-join.md
@@ -0,0 +1,448 @@
+---
+{
+ "title": "Colocation Join",
+ "language": "zh-CN"
+}
+---
+
+
+
+# Colocation Join
+
+Colocation Join 是在 Doris 0.9 版本中引入的新功能。旨在为某些 Join 查询提供本地性优化,来减少数据在节点间的传输耗时,加速查询。
+
+最初的设计、实现和效果可以参阅 [ISSUE 245](https://github.com/apache/incubator-doris/issues/245)。
+
+Colocation Join 功能经过一次改版,设计和使用方式和最初设计稍有不同。本文档主要介绍 Colocation Join 的原理、实现、使用方式和注意事项。
+
+## 名词解释
+
+* FE:Frontend,Doris 的前端节点。负责元数据管理和请求接入。
+* BE:Backend,Doris 的后端节点。负责查询执行和数据存储。
+* Colocation Group(CG):一个 CG 中会包含一张及以上的 Table。在同一个 Group 内的 Table 有着相同的 Colocation Group Schema,并且有着相同的数据分片分布。
+* Colocation Group Schema(CGS):用于描述一个 CG 中的 Table,和 Colocation 相关的通用 Schema 信息。包括分桶列类型,分桶数以及副本数等。
+
+## 原理
+
+Colocation Join 功能,是将一组拥有相同 CGS 的 Table 组成一个 CG。并保证这些 Table 对应的数据分片会落在同一个 BE 节点上。使得当 CG 内的表进行分桶列上的 Join 操作时,可以通过直接进行本地数据 Join,减少数据在节点间的传输耗时。
+
+一个表的数据,最终会根据分桶列值 Hash、对桶数取模的后落在某一个分桶内。假设一个 Table 的分桶数为 8,则共有 `[0, 1, 2, 3, 4, 5, 6, 7]` 8 个分桶(Bucket),我们称这样一个序列为一个 `BucketsSequence`。每个 Bucket 内会有一个或多个数据分片(Tablet)。当表为单分区表时,一个 Bucket 内仅有一个 Tablet。如果是多分区表,则会有多个。
+
+为了使得 Table 能够有相同的数据分布,同一 CG 内的 Table 必须保证以下属性相同:
+
+1. 分桶列和分桶数
+
+ 分桶列,即在建表语句中 `DISTRIBUTED BY HASH(col1, col2, ...)` 中指定的列。分桶列决定了一张表的数据通过哪些列的值进行 Hash 划分到不同的 Tablet 中。同一 CG 内的 Table 必须保证分桶列的类型和数量完全一致,并且桶数一致,才能保证多张表的数据分片能够一一对应的进行分布控制。
+
+2. 副本数
+
+ 同一个 CG 内所有表的所有分区(Partition)的副本数必须一致。如果不一致,可能出现某一个 Tablet 的某一个副本,在同一个 BE 上没有其他的表分片的副本对应。
+
+同一个 CG 内的表,分区的个数、范围以及分区列的类型不要求一致。
+
+在固定了分桶列和分桶数后,同一个 CG 内的表会拥有相同的 BucketsSequnce。而副本数决定了每个分桶内的 Tablet 的多个副本,存放在哪些 BE 上。假设 BucketsSequnce 为 `[0, 1, 2, 3, 4, 5, 6, 7]`,BE 节点有 `[A, B, C, D]` 4个。则一个可能的数据分布如下:
+
+```
++---+ +---+ +---+ +---+ +---+ +---+ +---+ +---+
+| 0 | | 1 | | 2 | | 3 | | 4 | | 5 | | 6 | | 7 |
++---+ +---+ +---+ +---+ +---+ +---+ +---+ +---+
+| A | | B | | C | | D | | A | | B | | C | | D |
+| | | | | | | | | | | | | | | |
+| B | | C | | D | | A | | B | | C | | D | | A |
+| | | | | | | | | | | | | | | |
+| C | | D | | A | | B | | C | | D | | A | | B |
++---+ +---+ +---+ +---+ +---+ +---+ +---+ +---+
+```
+
+CG 内所有表的数据都会按照上面的规则进行统一分布,这样就保证了,分桶列值相同的数据都在同一个 BE 节点上,可以进行本地数据 Join。
+
+## 使用方式
+
+### 建表
+
+建表时,可以在 `PROPERTIES` 中指定属性 `"colocate_with" = "group_name"`,表示这个表是一个 Colocation Join 表,并且归属于一个指定的 Colocation Group。
+
+示例:
+
+```
+CREATE TABLE tbl (k1 int, v1 int sum)
+DISTRIBUTED BY HASH(k1)
+BUCKETS 8
+PROPERTIES(
+ "colocate_with" = "group1"
+);
+```
+
+如果指定的 Group 不存在,则 Doris 会自动创建一个只包含当前这张表的 Group。如果 Group 已存在,则 Doris 会检查当前表是否满足 Colocation Group Schema。如果满足,则会创建该表,并将该表加入 Group。同时,表会根据已存在的 Group 中的数据分布规则创建分片和副本。
+Group 归属于一个 Database,Group 的名字在一个 Database 内唯一。在内部存储是 Group 的全名为 `dbId_groupName`,但用户只感知 groupName。
+
+### 删表
+
+当 Group 中最后一张表彻底删除后(彻底删除是指从回收站中删除。通常,一张表通过 `DROP TABLE` 命令删除后,会在回收站默认停留一天的时间后,再删除),该 Group 也会被自动删除。
+
+### 查看 Group
+
+以下命令可以查看集群内已存在的 Group 信息。
+
+```
+SHOW PROC '/colocation_group';
+
++-------------+--------------+--------------+------------+----------------+----------+----------+
+| GroupId | GroupName | TableIds | BucketsNum | ReplicationNum | DistCols | IsStable |
++-------------+--------------+--------------+------------+----------------+----------+----------+
+| 10005.10008 | 10005_group1 | 10007, 10040 | 10 | 3 | int(11) | true |
++-------------+--------------+--------------+------------+----------------+----------+----------+
+```
+
+* GroupId: 一个 Group 的全集群唯一标识,前半部分为 db id,后半部分为 group id。
+* GroupName: Group 的全名。
+* TabletIds: 该 Group 包含的 Table 的 id 列表。
+* BucketsNum: 分桶数。
+* ReplicationNum: 副本数。
+* DistCols: Distribution columns,即分桶列类型。
+* IsStable: 该 Group 是否稳定(稳定的定义,见 `Colocation 副本均衡和修复` 一节)。
+
+通过以下命令可以进一步查看一个 Group 的数据分布情况:
+
+```
+SHOW PROC '/colocation_group/10005.10008';
+
++-------------+---------------------+
+| BucketIndex | BackendIds |
++-------------+---------------------+
+| 0 | 10004, 10002, 10001 |
+| 1 | 10003, 10002, 10004 |
+| 2 | 10002, 10004, 10001 |
+| 3 | 10003, 10002, 10004 |
+| 4 | 10002, 10004, 10003 |
+| 5 | 10003, 10002, 10001 |
+| 6 | 10003, 10004, 10001 |
+| 7 | 10003, 10004, 10002 |
++-------------+---------------------+
+```
+
+* BucketIndex: 分桶序列的下标。
+* BackendIds: 分桶中数据分片所在的 BE 节点 id 列表。
+
+> 以上命令需要 AMDIN 权限。暂不支持普通用户查看。
+
+### 修改表 Colocate Group 属性
+
+可以对一个已经创建的表,修改其 Colocation Group 属性。示例:
+
+`ALTER TABLE tbl SET ("colocate_with" = "group2");`
+
+* 如果该表之前没有指定过 Group,则该命令检查 Schema,并将该表加入到该 Group(Group 不存在则会创建)。
+* 如果该表之前有指定其他 Group,则该命令会先将该表从原有 Group 中移除,并加入新 Group(Group 不存在则会创建)。
+
+也可以通过以下命令,删除一个表的 Colocation 属性:
+
+`ALTER TABLE tbl SET ("colocate_with" = "");`
+
+### 其他相关操作
+
+当对一个具有 Colocation 属性的表进行增加分区(ADD PARTITION)、修改副本数时,Doris 会检查修改是否会违反 Colocation Group Schema,如果违反则会拒绝。
+
+## Colocation 副本均衡和修复
+
+Colocation 表的副本分布需要遵循 Group 中指定的分布,所以在副本修复和均衡方面和普通分片有所区别。
+
+Group 自身有一个 Stable 属性,当 Stable 为 true 时,表示当前 Group 内的表的所有分片没有正在进行变动,Colocation 特性可以正常使用。当 Stable 为 false 时(Unstable),表示当前 Group 内有部分表的分片正在做修复或迁移,此时,相关表的 Colocation Join 将退化为普通 Join。
+
+### 副本修复
+
+副本只能存储在指定的 BE 节点上。所以当某个 BE 不可用时(宕机、Decommission 等),需要寻找一个新的 BE 进行替换。Doris 会优先寻找负载最低的 BE 进行替换。替换后,该 Bucket 内的所有在旧 BE 上的数据分片都要做修复。迁移过程中,Group 被标记为 Unstable。
+
+### 副本均衡
+
+Doris 会尽力将 Colocation 表的分片均匀分布在所有 BE 节点上。对于普通表的副本均衡,是以单副本为粒度的,即单独为每一个副本寻找负载较低的 BE 节点即可。而 Colocation 表的均衡是 Bucket 级别的,即一个 Bucket 内的所有副本都会一起迁移。我们采用一个简单的均衡算法,即在不考虑副本实际大小,而只根据副本数量,将 BucketsSequnce 均匀的分布在所有 BE 上。具体算法可以参阅 `ColocateTableBalancer.java` 中的代码注释。
+
+> 注1:当前的 Colocation 副本均衡和修复算法,对于异构部署的 Doris 集群效果可能不佳。所谓异构部署,即 BE 节点的磁盘容量、数量、磁盘类型(SSD 和 HDD)不一致。在异构部署情况下,可能出现小容量的 BE 节点和大容量的 BE 节点存储了相同的副本数量。
+>
+> 注2:当一个 Group 处于 Unstable 状态时,其中的表的 Join 将退化为普通 Join。此时可能会极大降低集群的查询性能。如果不希望系统自动均衡,可以设置 FE 的配置项 `disable_colocate_balance` 来禁止自动均衡。然后在合适的时间打开即可。(具体参阅 `高级操作` 一节)
+
+## 查询
+
+对 Colocation 表的查询方式和普通表一样,用户无需感知 Colocation 属性。如果 Colocation 表所在的 Group 处于 Unstable 状态,将自动退化为普通 Join。
+
+举例说明:
+
+表1:
+
+```
+CREATE TABLE `tbl1` (
+ `k1` date NOT NULL COMMENT "",
+ `k2` int(11) NOT NULL COMMENT "",
+ `v1` int(11) SUM NOT NULL COMMENT ""
+) ENGINE=OLAP
+AGGREGATE KEY(`k1`, `k2`)
+PARTITION BY RANGE(`k1`)
+(
+ PARTITION p1 VALUES LESS THAN ('2019-05-31'),
+ PARTITION p2 VALUES LESS THAN ('2019-06-30')
+)
+DISTRIBUTED BY HASH(`k2`) BUCKETS 8
+PROPERTIES (
+ "colocate_with" = "group1"
+);
+```
+
+表2:
+
+```
+CREATE TABLE `tbl2` (
+ `k1` datetime NOT NULL COMMENT "",
+ `k2` int(11) NOT NULL COMMENT "",
+ `v1` double SUM NOT NULL COMMENT ""
+) ENGINE=OLAP
+AGGREGATE KEY(`k1`, `k2`)
+DISTRIBUTED BY HASH(`k2`) BUCKETS 8
+PROPERTIES (
+ "colocate_with" = "group1"
+);
+```
+
+查看查询计划:
+
+```
+DESC SELECT * FROM tbl1 INNER JOIN tbl2 ON (tbl1.k2 = tbl2.k2);
+
++----------------------------------------------------+
+| Explain String |
++----------------------------------------------------+
+| PLAN FRAGMENT 0 |
+| OUTPUT EXPRS:`tbl1`.`k1` | |
+| PARTITION: RANDOM |
+| |
+| RESULT SINK |
+| |
+| 2:HASH JOIN |
+| | join op: INNER JOIN |
+| | hash predicates: |
+| | colocate: true |
+| | `tbl1`.`k2` = `tbl2`.`k2` |
+| | tuple ids: 0 1 |
+| | |
+| |----1:OlapScanNode |
+| | TABLE: tbl2 |
+| | PREAGGREGATION: OFF. Reason: null |
+| | partitions=0/1 |
+| | rollup: null |
+| | buckets=0/0 |
+| | cardinality=-1 |
+| | avgRowSize=0.0 |
+| | numNodes=0 |
+| | tuple ids: 1 |
+| | |
+| 0:OlapScanNode |
+| TABLE: tbl1 |
+| PREAGGREGATION: OFF. Reason: No AggregateInfo |
+| partitions=0/2 |
+| rollup: null |
+| buckets=0/0 |
+| cardinality=-1 |
+| avgRowSize=0.0 |
+| numNodes=0 |
+| tuple ids: 0 |
++----------------------------------------------------+
+```
+如果 Colocation Join 生效,则 Hash Join 节点会显示 `colocate: true`。
+
+如果没有生效,则查询计划如下:
+
+```
++----------------------------------------------------+
+| Explain String |
++----------------------------------------------------+
+| PLAN FRAGMENT 0 |
+| OUTPUT EXPRS:`tbl1`.`k1` | |
+| PARTITION: RANDOM |
+| |
+| RESULT SINK |
+| |
+| 2:HASH JOIN |
+| | join op: INNER JOIN (BROADCAST) |
+| | hash predicates: |
+| | colocate: false, reason: group is not stable |
+| | `tbl1`.`k2` = `tbl2`.`k2` |
+| | tuple ids: 0 1 |
+| | |
+| |----3:EXCHANGE |
+| | tuple ids: 1 |
+| | |
+| 0:OlapScanNode |
+| TABLE: tbl1 |
+| PREAGGREGATION: OFF. Reason: No AggregateInfo |
+| partitions=0/2 |
+| rollup: null |
+| buckets=0/0 |
+| cardinality=-1 |
+| avgRowSize=0.0 |
+| numNodes=0 |
+| tuple ids: 0 |
+| |
+| PLAN FRAGMENT 1 |
+| OUTPUT EXPRS: |
+| PARTITION: RANDOM |
+| |
+| STREAM DATA SINK |
+| EXCHANGE ID: 03 |
+| UNPARTITIONED |
+| |
+| 1:OlapScanNode |
+| TABLE: tbl2 |
+| PREAGGREGATION: OFF. Reason: null |
+| partitions=0/1 |
+| rollup: null |
+| buckets=0/0 |
+| cardinality=-1 |
+| avgRowSize=0.0 |
+| numNodes=0 |
+| tuple ids: 1 |
++----------------------------------------------------+
+```
+
+HASH JOIN 节点会显示对应原因:`colocate: false, reason: group is not stable`。同时会有一个 EXCHANGE 节点生成。
+
+
+## 高级操作
+
+### FE 配置项
+
+* disable\_colocate\_relocate
+
+ 是否关闭 Doris 的自动 Colocation 副本修复。默认为 false,即不关闭。该参数只影响 Colocation 表的副本修复,不影响普通表。
+
+* disable\_colocate\_balance
+
+ 是否关闭 Doris 的自动 Colocation 副本均衡。默认为 false,即不关闭。该参数只影响 Colocation 表的副本均衡,不影响普通表。
+
+以上参数可以动态修改,设置方式请参阅 `HELP ADMIN SHOW CONFIG;` 和 `HELP ADMIN SET CONFIG;`。
+
+* disable\_colocate\_join
+
+ 是否关闭 Colocation Join 功能。在 0.10 及之前的版本,默认为 true,即关闭。在之后的某个版本中将默认为 false,即开启。
+
+* use\_new\_tablet\_scheduler
+
+ 在 0.10 及之前的版本中,新的副本调度逻辑与 Colocation Join 功能不兼容,所以在 0.10 及之前版本,如果 `disable_colocate_join = false`,则需设置 `use_new_tablet_scheduler = false`,即关闭新的副本调度器。之后的版本中,`use_new_tablet_scheduler` 将衡为 true。
+
+### HTTP Restful API
+
+Doris 提供了几个和 Colocation Join 有关的 HTTP Restful API,用于查看和修改 Colocation Group。
+
+该 API 实现在 FE 端,使用 `fe_host:fe_http_port` 进行访问。需要 ADMIN 权限。
+
+1. 查看集群的全部 Colocation 信息
+
+ ```
+ GET /api/colocate
+
+ 返回以 Json 格式表示内部 Colocation 信息。
+
+ {
+ "colocate_meta": {
+ "groupName2Id": {
+ "g1": {
+ "dbId": 10005,
+ "grpId": 10008
+ }
+ },
+ "group2Tables": {},
+ "table2Group": {
+ "10007": {
+ "dbId": 10005,
+ "grpId": 10008
+ },
+ "10040": {
+ "dbId": 10005,
+ "grpId": 10008
+ }
+ },
+ "group2Schema": {
+ "10005.10008": {
+ "groupId": {
+ "dbId": 10005,
+ "grpId": 10008
+ },
+ "distributionColTypes": [{
+ "type": "INT",
+ "len": -1,
+ "isAssignedStrLenInColDefinition": false,
+ "precision": 0,
+ "scale": 0
+ }],
+ "bucketsNum": 10,
+ "replicationNum": 2
+ }
+ },
+ "group2BackendsPerBucketSeq": {
+ "10005.10008": [
+ [10004, 10002],
+ [10003, 10002],
+ [10002, 10004],
+ [10003, 10002],
+ [10002, 10004],
+ [10003, 10002],
+ [10003, 10004],
+ [10003, 10004],
+ [10003, 10004],
+ [10002, 10004]
+ ]
+ },
+ "unstableGroups": []
+ },
+ "status": "OK"
+ }
+ ```
+
+2. 将 Group 标记为 Stable 或 Unstable
+
+ * 标记为 Stable
+
+ ```
+ POST /api/colocate/group_stable?db_id=10005&group_id=10008
+
+ 返回:200
+ ```
+
+ * 标记为 Unstable
+
+ ```
+ DELETE /api/colocate/group_stable?db_id=10005&group_id=10008
+
+ 返回:200
+ ```
+
+3. 设置 Group 的数据分布
+
+ 该接口可以强制设置某一 Group 的数分布。
+
+ ```
+ POST /api/colocate/bucketseq?db_id=10005&group_id= 10008
+
+ Body:
+ [[10004,10002],[10003,10002],[10002,10004],[10003,10002],[10002,10004],[10003,10002],[10003,10004],[10003,10004],[10003,10004],[10002,10004]]
+
+ 返回 200
+ ```
+ 其中 Body 是以嵌套数组表示的 BucketsSequence 以及每个 Bucket 中分片分布所在 BE 的 id。
+
+ 注意,使用该命令,可能需要将 FE 的配置 `disable_colocate_relocate` 和 `disable_colocate_balance` 设为 true。即关闭系统自动的 Colocation 副本修复和均衡。否则可能在修改后,会被系统自动重置。
\ No newline at end of file
diff --git a/docs/zh-CN/administrator-guide/config/fe_config.md b/docs/zh-CN/administrator-guide/config/fe_config.md
new file mode 100644
index 00000000000000..6c273c5503e65c
--- /dev/null
+++ b/docs/zh-CN/administrator-guide/config/fe_config.md
@@ -0,0 +1,41 @@
+---
+{
+ "title": "基本配置",
+ "language": "zh-CN"
+}
+---
+
+
+
+# 基本配置
+
+## brpc_max_body_size
+
+ 这个配置主要用来修改 brpc 的参数 max_body_size ,默认配置是 64M。一般发生在 multi distinct + 无 group by + 超过1T 数据量的情况下。尤其如果发现查询卡死,且 BE 出现类似 body_size is too large 的字样。
+
+ 由于这是一个 brpc 的配置,用户也可以在运行中直接修改该参数。通过访问 http://host:brpc_port/flags 修改。
+
+## max_running_txn_num_per_db
+
+ 这个配置主要是用来控制同一个 db 的并发导入个数的,默认配置是100。当导入的并发执行的个数超过这个配置的值的时候,同步执行的导入就会失败比如 stream load。异步执行的导入就会一直处在 pending 状态比如 broker load。
+
+ 一般来说不推荐更改这个并发数。如果当前导入并发超过这个值,则需要先检查是否单个导入任务过慢,或者小文件太多没有合并后导入的问题。
+
+ 报错信息比如:current running txns on db xxx is xx, larger than limit xx。就属于这类问题。
diff --git a/docs/zh-CN/administrator-guide/dynamic-partition.md b/docs/zh-CN/administrator-guide/dynamic-partition.md
new file mode 100644
index 00000000000000..4705fbc109fdbd
--- /dev/null
+++ b/docs/zh-CN/administrator-guide/dynamic-partition.md
@@ -0,0 +1,208 @@
+---
+{
+ "title": "动态分区",
+ "language": "zh-CN"
+}
+---
+
+
+
+# 动态分区
+
+动态分区是在 Doris 0.12 版本中引入的新功能。旨在对表级别的分区实现生命周期管理(TTL),减少用户的使用负担。
+
+最初的设计、实现和效果可以参阅 [ISSUE 2262](https://github.com/apache/incubator-doris/issues/2262)。
+
+目前实现了动态添加分区及动态删除分区的功能。
+
+## 名词解释
+
+* FE:Frontend,Doris 的前端节点。负责元数据管理和请求接入。
+* BE:Backend,Doris 的后端节点。负责查询执行和数据存储。
+
+## 原理
+
+在某些使用场景下,用户会将表按照天进行分区划分,每天定时执行例行任务,这时需要使用方手动管理分区,否则可能由于使用方没有创建分区导致数据导入失败,这给使用方带来了额外的维护成本。
+
+在实现方式上, FE会启动一个后台线程,根据fe.conf中`dynamic_partition_enable` 及 `dynamic_partition_check_interval_seconds`参数决定该线程是否启动以及该线程的调度频率。每次调度时,会在注册表中读取动态分区表的属性,并根据动态分区属性动态添加及删除分区。
+
+建表时,在properties中指定dynamic_partition属性,FE首先对动态分区属性进行解析,校验输入参数的合法性,然后将对应的属性持久化到FE的元数据中,并将该表注册到动态分区列表中,后台线程会根据配置参数定期对动态分区列表进行扫描,读取表的动态分区属性,执行添加分区及删除分区的任务,每次的调度信息会保留在FE的内存中(重启后则丢失),可以通过`SHOW DYNAMIC PARTITION TABLES`查看调度任务是否成功,如果存在分区创建或删除失败,会将失败信息输出。
+
+## 使用方式
+
+### 动态分区属性参数说明:
+
+`dynamic_partition.enable`: 是否开启动态分区特性,可指定为 `TRUE` 或 `FALSE`。如果不填写,默认为 `TRUE`。
+
+
+`dynamic_partition.time_unit`: 动态分区调度的单位,可指定为 `DAY` `WEEK` `MONTH`,当指定为 `DAY` 时,动态创建的分区名后缀格式为`yyyyMMdd`,例如`20200325`。当指定为 `WEEK` 时,动态创建的分区名后缀格式为`yyyy_ww`即当前日期属于这一年的第几周,例如 `2020-03-25` 创建的分区名后缀为 `2020_13`, 表明目前为2020年第13周。当指定为 `MONTH` 时,动态创建的分区名后缀格式为 `yyyyMM`,例如 `202003`。
+
+`dynamic_partition.start`: 动态分区的开始时间, 以当天为基准,超过该时间范围的分区将会被删除。如果不填写,则默认为`Integer.MIN_VALUE` 即 `-2147483648`。
+
+
+`dynamic_partition.end`: 动态分区的结束时间, 以当天为基准,会提前创建N个单位的分区范围。
+
+`dynamic_partition.prefix`: 动态创建的分区名前缀。
+
+`dynamic_partition.buckets`: 动态创建的分区所对应的分桶数量。
+
+### 建表
+
+建表时,可以在 `PROPERTIES` 中指定以下`dynamic_partition`属性,表示这个表是一个动态分区表。
+
+示例:
+
+```
+CREATE TABLE example_db.dynamic_partition
+(
+k1 DATE,
+k2 INT,
+k3 SMALLINT,
+v1 VARCHAR(2048),
+v2 DATETIME DEFAULT "2014-02-04 15:36:00"
+)
+ENGINE=olap
+DUPLICATE KEY(k1, k2, k3)
+PARTITION BY RANGE (k1)
+(
+PARTITION p20200321 VALUES LESS THAN ("2020-03-22"),
+PARTITION p20200322 VALUES LESS THAN ("2020-03-23"),
+PARTITION p20200323 VALUES LESS THAN ("2020-03-24"),
+PARTITION p20200324 VALUES LESS THAN ("2020-03-25")
+)
+DISTRIBUTED BY HASH(k2) BUCKETS 32
+PROPERTIES(
+"storage_medium" = "SSD",
+"dynamic_partition.enable" = "true",
+"dynamic_partition.time_unit" = "DAY",
+"dynamic_partition.start" = "-3",
+"dynamic_partition.end" = "3",
+"dynamic_partition.prefix" = "p",
+"dynamic_partition.buckets" = "32"
+ );
+```
+创建一张动态分区表,指定开启动态分区特性,以当天为2020-03-25为例,在每次调度时,会删除分区上界小于 `2020-03-22` 的分区,为了避免删除非动态创建的分区,动态删除分区只会删除分区名符合动态创建分区规则的分区,例如分区名为a1, 则即使分区范围在待删除的分区范围内,也不会被删除。同时在调度时会提前创建今天以及以后3天(总共4天)的分区(若分区已存在则会忽略),分区名根据指定前缀分别为`p20200325` `p20200326` `p20200327` `p20200328`,每个分区的分桶数量为32。同时会删除 `p20200321` 的分区,最终的分区范围如下:
+```
+[types: [DATE]; keys: [2020-03-22]; ‥types: [DATE]; keys: [2020-03-23]; )
+[types: [DATE]; keys: [2020-03-23]; ‥types: [DATE]; keys: [2020-03-24]; )
+[types: [DATE]; keys: [2020-03-24]; ‥types: [DATE]; keys: [2020-03-25]; )
+[types: [DATE]; keys: [2020-03-25]; ‥types: [DATE]; keys: [2020-03-26]; )
+[types: [DATE]; keys: [2020-03-26]; ‥types: [DATE]; keys: [2020-03-27]; )
+[types: [DATE]; keys: [2020-03-27]; ‥types: [DATE]; keys: [2020-03-28]; )
+[types: [DATE]; keys: [2020-03-28]; ‥types: [DATE]; keys: [2020-03-29]; )
+```
+
+### 开启动态分区功能
+1. 首先需要在fe.conf中设置`dynamic_partition_enable=true`,可以在集群启动时通过修改配置文件指定,或者通过MySQL连接后使用命令行 `ADMIN SET FRONTEND CONFIG ("dynamic_partition_enable" = "true")`修改,也可以在运行时通过http接口动态修改,修改方法查看高级操作部分
+
+2. 如果需要对0.12版本之前的表添加动态分区属性,则需要通过以下命令修改表的属性
+```
+ALTER TABLE dynamic_partition set ("dynamic_partition.enable" = "true", "dynamic_partition.time_unit" = "DAY", "dynamic_partition.end" = "3", "dynamic_partition.prefix" = "p", "dynamic_partition.buckets" = "32");
+```
+
+### 停止动态分区功能
+
+如果需要对集群中所有动态分区表停止动态分区功能,则需要在fe.conf中设置`dynamic_partition_enable=false`
+
+如果需要对指定表停止动态分区功能,则可以通过以下命令修改表的属性
+```
+ALTER TABLE dynamic_partition SET ("dynamic_partition.enable" = "false")
+```
+
+### 修改动态分区属性
+
+通过如下命令可以修改动态分区的属性
+```
+ALTER TABLE dynamic_partition SET ("key" = "value")
+```
+
+### 查看动态分区表调度情况
+
+通过以下命令可以进一步查看动态分区表的调度情况:
+
+```
+SHOW DYNAMIC PARTITION TABLES;
+
++-------------------+--------+----------+-------+------+--------+---------+---------------------+---------------------+--------+------------------------+----------------------+
+| TableName | Enable | TimeUnit | Start | End | Prefix | Buckets | LastUpdateTime | LastSchedulerTime | State | LastCreatePartitionMsg | LastDropPartitionMsg |
++-------------------+--------+----------+-------+------+--------+---------+---------------------+---------------------+--------+------------------------+----------------------+
+| dynamic_partition | true | DAY | -3 | 3 | p | 32 | 2020-03-12 17:25:47 | 2020-03-12 17:25:52 | NORMAL | N/A | N/A |
++-------------------+--------+----------+-------+------+--------+---------+---------------------+---------------------+--------+------------------------+----------------------+
+1 row in set (0.00 sec)
+
+```
+
+* LastUpdateTime: 最后一次修改动态分区属性的时间
+* LastSchedulerTime: 最后一次执行动态分区调度的时间
+* State: 最后一次执行动态分区调度的状态
+* LastCreatePartitionMsg: 最后一次执行动态添加分区调度的错误信息
+* LastDropPartitionMsg: 最后一次执行动态删除分区调度的错误信息
+
+## 高级操作
+
+### FE 配置项
+
+* dynamic\_partition\_enable
+
+ 是否开启 Doris 的动态分区功能。默认为 false,即关闭。该参数只影响动态分区表的分区操作,不影响普通表。
+
+* dynamic\_partition\_check\_interval\_seconds
+
+ 动态分区线程的执行频率,默认为3600(1个小时),即每1个小时进行一次调度
+
+### HTTP Restful API
+
+Doris 提供了修改动态分区配置参数的 HTTP Restful API,用于运行时修改动态分区配置参数。
+
+该 API 实现在 FE 端,使用 `fe_host:fe_http_port` 进行访问。需要 ADMIN 权限。
+
+1. 将 dynamic_partition_enable 设置为 true 或 false
+
+ * 标记为 true
+
+ ```
+ GET /api/_set_config?dynamic_partition_enable=true
+
+ 例如: curl --location-trusted -u username:password -XGET http://fe_host:fe_http_port/api/_set_config?dynamic_partition_enable=true
+
+ 返回:200
+ ```
+
+ * 标记为 false
+
+ ```
+ GET /api/_set_config?dynamic_partition_enable=false
+
+ 例如: curl --location-trusted -u username:password -XGET http://fe_host:fe_http_port/api/_set_config?dynamic_partition_enable=false
+
+ 返回:200
+ ```
+
+2. 设置 dynamic partition 的调度频率
+
+ * 设置调度时间为12小时调度一次
+
+ ```
+ GET /api/_set_config?dynamic_partition_check_interval_seconds=432000
+
+ 例如: curl --location-trusted -u username:password -XGET http://fe_host:fe_http_port/api/_set_config?dynamic_partition_check_interval_seconds=432000
+
+ 返回:200
+ ```
diff --git a/docs/documentation/cn/administrator-guide/export-manual.md b/docs/zh-CN/administrator-guide/export-manual.md
similarity index 99%
rename from docs/documentation/cn/administrator-guide/export-manual.md
rename to docs/zh-CN/administrator-guide/export-manual.md
index 7af73acfdf68bc..0c0845bba61a13 100644
--- a/docs/documentation/cn/administrator-guide/export-manual.md
+++ b/docs/zh-CN/administrator-guide/export-manual.md
@@ -1,3 +1,10 @@
+---
+{
+ "title": "数据导出",
+ "language": "zh-CN"
+}
+---
+
+
+# CANCEL LABEL
+## description
+ NAME:
+ cancel_label: cancel a transaction with label
+
+ SYNOPSIS
+ curl -u user:passwd -XPOST http://host:port/api/{db}/{label}/_cancel
+
+ DESCRIPTION
+ 该命令用于cancel一个指定Label对应的事务,事务在Prepare阶段能够被成功cancel
+
+ RETURN VALUES
+ 执行完成后,会以Json格式返回这次导入的相关内容。当前包括一下字段
+ Status: 是否成功cancel
+ Success: 成功cancel事务
+ 其他: cancel失败
+ Message: 具体的失败信息
+
+ ERRORS
+
+## example
+
+ 1. cancel testDb, testLabel的作业
+ curl -u root -XPOST http://host:port/api/testDb/testLabel/_cancel
+
+## keyword
+ CANCEL,LABEL
+
+
+
+
+
+
diff --git a/docs/zh-CN/administrator-guide/http-actions/compaction-action.md b/docs/zh-CN/administrator-guide/http-actions/compaction-action.md
new file mode 100644
index 00000000000000..ddf7d1f90be8ce
--- /dev/null
+++ b/docs/zh-CN/administrator-guide/http-actions/compaction-action.md
@@ -0,0 +1,86 @@
+---
+{
+ "title": "Compaction Action",
+ "language": "zh-CN"
+}
+---
+
+
+
+# Compaction Action
+
+该 API 用于查看某个 BE 节点总体的 compaction 状态,或者指定 tablet 的 compaction 状态。也可以用于手动触发 Compaction。
+
+## 查看 Compaction 状态
+
+### 节点整体 compaction 状态
+
+(TODO)
+
+### 指定 tablet 的 compaction 状态
+
+```
+curl -X GET http://be_host:webserver_port/api/compaction/show?tablet_id=xxxx\&schema_hash=yyyy
+```
+
+若 tablet 不存在,返回 JSON 格式的错误:
+
+```
+{
+ "status": "Fail",
+ "msg": "Tablet not found"
+}
+```
+
+若 tablet 存在,则返回 JSON 格式的结果:
+
+```
+{
+ "cumulative point": 50,
+ "last cumulative failure time": "2019-12-16 18:13:43.224",
+ "last base failure time": "2019-12-16 18:13:23.320",
+ "last cumu success time": "2019-12-16 18:12:15.110",
+ "last base success time": "2019-12-16 18:11:50.780",
+ "rowsets": [
+ "[0-48] 10 DATA OVERLAPPING",
+ "[49-49] 2 DATA OVERLAPPING",
+ "[50-50] 0 DELETE NONOVERLAPPING",
+ "[51-51] 5 DATA OVERLAPPING"
+ ]
+}
+```
+
+结果说明:
+
+* cumulative point:base 和 cumulative compaction 的版本分界线。在 point(不含)之前的版本由 base compaction 处理。point(含)之后的版本由 cumulative compaction 处理。
+* last cumulative failure time:上一次尝试 cumulative compaction 失败的时间。默认 10min 后才会再次尝试对该 tablet 做 cumulative compaction。
+* last base failure time:上一次尝试 base compaction 失败的时间。默认 10min 后才会再次尝试对该 tablet 做 base compaction。
+* rowsets:该 tablet 当前的 rowset 集合。如 [0-48] 表示 0-48 版本。第二位数字表示该版本中 segment 的数量。`DELETE` 表示 delete 版本。`DATA` 表示数据版本。`OVERLAPPING` 和 `NONOVERLAPPING` 表示segment数据是否重叠。
+
+### 示例
+
+```
+curl -X GET http://192.168.10.24:8040/api/compaction/show?tablet_id=10015\&schema_hash=1294206575
+```
+
+## 手动触发 Compaction
+
+(TODO)
+
diff --git a/docs/zh-CN/administrator-guide/http-actions/fe-get-log-file.md b/docs/zh-CN/administrator-guide/http-actions/fe-get-log-file.md
new file mode 100644
index 00000000000000..47ac508e172cc4
--- /dev/null
+++ b/docs/zh-CN/administrator-guide/http-actions/fe-get-log-file.md
@@ -0,0 +1,80 @@
+---
+{
+ "title": "get\\_log\\_file",
+ "language": "zh-CN"
+}
+---
+
+
+
+# get\_log\_file
+
+用户可以通过该 HTTP 接口获取 FE 的日志文件。
+
+## 日志类型
+
+支持获取以下类型的 FE 日志:
+
+1. fe.audit.log(审计日志)
+
+ 审计日志记录了对应 FE 节点的所有请求语句已经请求的信息。审计日志的文件命名规则如下:
+
+ ```
+ fe.audit.log # 当前的最新日志
+ fe.audit.log.20190603.1 # 对应日期的审计日志,当对应日期的日志大小超过 1GB 后,会生成序号后缀。序号越小的日志,内容越新。
+ fe.audit.log.20190603.2
+ fe.audit.log.20190602.1
+ ...
+ ```
+
+## 接口示例
+
+1. 获取对应类型的日志文件列表
+
+ 示例:
+
+ `curl -v -X HEAD -uuser:passwd http://fe_host:http_port/api/get_log_file?type=fe.audit.log`
+
+ 返回结果:
+
+ ```
+ HTTP/1.1 200 OK
+ file_infos: {"fe.audit.log":24759,"fe.audit.log.20190528.1":132934}
+ content-type: text/html
+ connection: keep-alive
+ ```
+
+ 在返回的 header 中,`file_infos` 字段以 json 格式展示文件列表以及对应文件大小(单位字节)
+
+2. 下载日志文件
+
+ 示例:
+
+ ```
+ curl -X GET -uuser:passwd http://fe_host:http_port/api/get_log_file?type=fe.audit.log\&file=fe.audit.log.20190528.1
+ ```
+
+ 返回结果:
+
+ 以文件的形式下载指定的文件。
+
+## 接口说明
+
+该接口需要 admin 权限。
diff --git a/docs/zh-CN/administrator-guide/http-actions/get-label-state.md b/docs/zh-CN/administrator-guide/http-actions/get-label-state.md
new file mode 100644
index 00000000000000..65f9210e94ed5b
--- /dev/null
+++ b/docs/zh-CN/administrator-guide/http-actions/get-label-state.md
@@ -0,0 +1,59 @@
+---
+{
+ "title": "GET LABEL STATE",
+ "language": "zh-CN"
+}
+---
+
+
+
+# GET LABEL STATE
+## description
+ NAME:
+ get_label_state: get label's state
+
+ SYNOPSIS
+ curl -u user:passwd http://host:port/api/{db}/{label}/_state
+
+ DESCRIPTION
+ 该命令用于查看一个Label对应的事务状态
+
+ RETURN VALUES
+ 执行完毕后,会以Json格式返回这次导入的相关内容。当前包括一下字段
+ Label:本次导入的 label,如果没有指定,则为一个 uuid。
+ Status:此命令是否成功执行,Success表示成功执行
+ Message: 具体的执行信息
+ State: 只有在Status为Success时才有意义
+ UNKNOWN: 没有找到对应的Label
+ PREPARE: 对应的事务已经prepare,但尚未提交
+ COMMITTED: 事务已经提交,不能被cancel
+ VISIBLE: 事务提交,并且数据可见,不能被cancel
+ ABORTED: 事务已经被ROLLBACK,导入已经失败。
+
+ ERRORS
+
+## example
+
+ 1. 获得testDb, testLabel的状态
+ curl -u root http://host:port/api/testDb/testLabel/_state
+
+## keyword
+ GET, LABEL, STATE
+
diff --git a/docs/zh-CN/administrator-guide/http-actions/restore-tablet.md b/docs/zh-CN/administrator-guide/http-actions/restore-tablet.md
new file mode 100644
index 00000000000000..786578e30adee5
--- /dev/null
+++ b/docs/zh-CN/administrator-guide/http-actions/restore-tablet.md
@@ -0,0 +1,43 @@
+---
+{
+ "title": "RESTORE TABLET",
+ "language": "zh-CN"
+}
+---
+
+
+
+# RESTORE TABLET
+## description
+
+ 该功能用于恢复trash目录中被误删的tablet数据。
+
+ 说明:这个功能暂时只在be服务中提供一个http接口。如果要使用,
+ 需要向要进行数据恢复的那台be机器的http端口发送restore tablet api请求。api格式如下:
+ METHOD: POST
+ URI: http://be_host:be_http_port/api/restore_tablet?tablet_id=xxx&schema_hash=xxx
+
+## example
+
+ curl -X POST "http://hostname:8088/api/restore_tablet?tablet_id=123456\&schema_hash=1111111"
+
+## keyword
+
+ RESTORE,TABLET,RESTORE,TABLET
diff --git a/docs/zh-CN/administrator-guide/load-data/broker-load-manual.md b/docs/zh-CN/administrator-guide/load-data/broker-load-manual.md
new file mode 100644
index 00000000000000..666b0c165d8031
--- /dev/null
+++ b/docs/zh-CN/administrator-guide/load-data/broker-load-manual.md
@@ -0,0 +1,517 @@
+---
+{
+ "title": "Broker Load",
+ "language": "zh-CN"
+}
+---
+
+
+
+# Broker Load
+
+Broker load 是一个异步的导入方式,支持的数据源取决于 Broker 进程支持的数据源。
+
+用户需要通过 MySQL 协议 创建 Broker load 导入,并通过查看导入命令检查导入结果。
+
+## 适用场景
+
+* 源数据在 Broker 可以访问的存储系统中,如 HDFS。
+* 数据量在 几十到百GB 级别。
+
+## 名词解释
+
+1. Frontend(FE):Doris 系统的元数据和调度节点。在导入流程中主要负责导入 plan 生成和导入任务的调度工作。
+2. Backend(BE):Doris 系统的计算和存储节点。在导入流程中主要负责数据的 ETL 和存储。
+3. Broker:Broker 为一个独立的无状态进程。封装了文件系统接口,提供 Doris 读取远端存储系统中文件的能力。
+4. Plan:导入执行计划,BE 会执行导入执行计划将数据导入到 Doris 系统中。
+
+## 基本原理
+
+用户在提交导入任务后,FE 会生成对应的 Plan 并根据目前 BE 的个数和文件的大小,将 Plan 分给 多个 BE 执行,每个 BE 执行一部分导入数据。
+
+BE 在执行的过程中会从 Broker 拉取数据,在对数据 transform 之后将数据导入系统。所有 BE 均完成导入,由 FE 最终决定导入是否成功。
+
+```
+ +
+ | 1. user create broker load
+ v
+ +----+----+
+ | |
+ | FE |
+ | |
+ +----+----+
+ |
+ | 2. BE etl and load the data
+ +--------------------------+
+ | | |
++---v---+ +--v----+ +---v---+
+| | | | | |
+| BE | | BE | | BE |
+| | | | | |
++---+-^-+ +---+-^-+ +--+-^--+
+ | | | | | |
+ | | | | | | 3. pull data from broker
++---v-+-+ +---v-+-+ +--v-+--+
+| | | | | |
+|Broker | |Broker | |Broker |
+| | | | | |
++---+-^-+ +---+-^-+ +---+-^-+
+ | | | | | |
++---v-+-----------v-+----------v-+-+
+| HDFS/BOS/AFS cluster |
+| |
++----------------------------------+
+
+```
+
+## 基本操作
+
+### 创建导入
+
+Broker load 创建导入语句
+
+语法:
+
+```
+LOAD LABEL db_name.label_name
+(data_desc, ...)
+WITH BROKER broker_name broker_properties
+[PROPERTIES (key1=value1, ... )]
+
+* data_desc:
+
+ DATA INFILE ('file_path', ...)
+ [NEGATIVE]
+ INTO TABLE tbl_name
+ [PARTITION (p1, p2)]
+ [COLUMNS TERMINATED BY separator ]
+ [(col1, ...)]
+ [SET (k1=f1(xx), k2=f2(xx))]
+ [WHERE predicate]
+
+* broker_properties:
+
+ (key1=value1, ...)
+```
+示例:
+
+```
+LOAD LABEL db1.label1
+(
+ DATA INFILE("hdfs://abc.com:8888/user/palo/test/ml/file1")
+ INTO TABLE tbl1
+ COLUMNS TERMINATED BY ","
+ (tmp_c1,tmp_c2)
+ SET
+ (
+ id=tmp_c2,
+ name=tmp_c1
+ ),
+ DATA INFILE("hdfs://abc.com:8888/user/palo/test/ml/file2")
+ INTO TABLE tbl2
+ COLUMNS TERMINATED BY ","
+ (col1, col2)
+ where col1 > 1
+)
+WITH BROKER 'broker'
+(
+ "username"="user",
+ "password"="pass"
+)
+PROPERTIES
+(
+ "timeout" = "3600"
+);
+
+```
+
+创建导入的详细语法执行 ```HELP BROKER LOAD``` 查看语法帮助。这里主要介绍 Broker load 的创建导入语法中参数意义和注意事项。
+
+#### Label
+
+导入任务的标识。每个导入任务,都有一个在单 database 内部唯一的 Label。Label 是用户在导入命令中自定义的名称。通过这个 Label,用户可以查看对应导入任务的执行情况。
+
+Label 的另一个作用,是防止用户重复导入相同的数据。**强烈推荐用户同一批次数据使用相同的label。这样同一批次数据的重复请求只会被接受一次,保证了 At-Most-Once 语义**
+
+当 Label 对应的导入作业状态为 CANCELLED 时,可以再次使用该 Label 提交导入作业。
+
+#### 数据描述类参数
+
+数据描述类参数主要指的是 Broker load 创建导入语句中的属于 ```data_desc``` 部分的参数。每组 ```data_desc ``` 主要表述了本次导入涉及到的数据源地址,ETL 函数,目标表及分区等信息。
+
+下面主要对数据描述类的部分参数详细解释:
+
++ 多表导入
+
+ Broker load 支持一次导入任务涉及多张表,每个 Broker load 导入任务可在多个 ``` data_desc ``` 声明多张表来实现多表导入。每个单独的 ```data_desc``` 还可以指定属于该表的数据源地址。Broker load 保证了单次导入的多张表之间原子性成功或失败。
+
++ negative
+
+ ```data_desc```中还可以设置数据取反导入。这个功能主要用于,当数据表中聚合列的类型都为 SUM 类型时。如果希望撤销某一批导入的数据。则可以通过 `negative` 参数导入同一批数据。Doris 会自动为这一批数据在聚合列上数据取反,以达到消除同一批数据的功能。
+
++ partition
+
+ 在 ```data_desc``` 中可以指定待导入表的 partition 信息,如果待导入数据不属于指定的 partition 则不会被导入。同时,不在指定 Partition 的数据会被认为是错误数据。
+
++ set column mapping
+
+ 在 ```data_desc``` 中的 SET 语句负责设置列函数变换,这里的列函数变换支持所有查询的等值表达式变换。如果原始数据的列和表中的列不一一对应,就需要用到这个属性。
+
++ where predicate
+
+ 在 ```data_desc``` 中的 WHERE 语句中负责过滤已经完成 transform 的数据,被 filter 的数据不会进入容忍率的统计中。如果多个 data_desc 中声明了同一张表的多个条件的话,则会 merge 同一张表的多个条件,merge 策略是 AND 。
+
+#### 导入作业参数
+
+导入作业参数主要指的是 Broker load 创建导入语句中的属于 ```opt_properties```部分的参数。导入作业参数是作用于整个导入作业的。
+
+下面主要对导入作业参数的部分参数详细解释:
+
++ timeout
+
+ 导入作业的超时时间(以秒为单位),用户可以在 ```opt_properties``` 中自行设置每个导入的超时时间。导入任务在设定的 timeout 时间内未完成则会被系统取消,变成 CANCELLED。Broker load 的默认导入超时时间为4小时。
+
+ 通常情况下,用户不需要手动设置导入任务的超时时间。当在默认超时时间内无法完成导入时,可以手动设置任务的超时时间。
+
+ > 推荐超时时间
+ >
+ > 总文件大小(MB) / 用户 Doris 集群最慢导入速度(MB/s) > timeout > ((总文件大小(MB) * 待导入的表及相关 Roll up 表的个数) / (10 * 导入并发数) )
+
+ > 导入并发数见文档最后的导入系统配置说明,公式中的 10 为目前的导入限速 10MB/s。
+
+ > 例如一个 1G 的待导入数据,待导入表包含3个 Rollup 表,当前的导入并发数为 3。则 timeout 的 最小值为 ```(1 * 1024 * 3 ) / (10 * 3) = 102 秒```
+
+ 由于每个 Doris 集群的机器环境不同且集群并发的查询任务也不同,所以用户 Doris 集群的最慢导入速度需要用户自己根据历史的导入任务速度进行推测。
+
++ max\_filter\_ratio
+
+ 导入任务的最大容忍率,默认为0容忍,取值范围是0~1。当导入的错误率超过该值,则导入失败。
+
+ 如果用户希望忽略错误的行,可以通过设置这个参数大于 0,来保证导入可以成功。
+
+ 计算公式为:
+
+ ``` max_filter_ratio = (dpp.abnorm.ALL / (dpp.abnorm.ALL + dpp.norm.ALL ) ) ```
+
+ ```dpp.abnorm.ALL``` 表示数据质量不合格的行数。如类型不匹配,列数不匹配,长度不匹配等等。
+
+ ```dpp.norm.ALL``` 指的是导入过程中正确数据的条数。可以通过 ```SHOW LOAD``` 命令查询导入任务的正确数据量。
+
+ 原始文件的行数 = `dpp.abnorm.ALL + dpp.norm.ALL`
+
++ exec\_mem\_limit
+
+ 导入内存限制。默认是 2GB。单位为字节。
+
++ strict\_mode
+
+ Broker load 导入可以开启 strict mode 模式。开启方式为 ```properties ("strict_mode" = "true")``` 。默认的 strict mode 为关闭。
+
+ strict mode 模式的意思是:对于导入过程中的列类型转换进行严格过滤。严格过滤的策略如下:
+
+ 1. 对于列类型转换来说,如果 strict mode 为true,则错误的数据将被 filter。这里的错误数据是指:原始数据并不为空值,在参与列类型转换后结果为空值的这一类数据。
+
+ 2. 对于导入的某列由函数变换生成时,strict mode 对其不产生影响。
+
+ 3. 对于导入的某列类型包含范围限制的,如果原始数据能正常通过类型转换,但无法通过范围限制的,strict mode 对其也不产生影响。例如:如果类型是 decimal(1,0), 原始数据为 10,则属于可以通过类型转换但不在列声明的范围内。这种数据 strict 对其不产生影响。
+
+#### strict mode 与 source data 的导入关系
+
+这里以列类型为 TinyInt 来举例
+
+>注:当表中的列允许导入空值时
+
+|source data | source data example | string to int | strict_mode | result|
+|------------|---------------------|-----------------|--------------------|---------|
+|空值 | \N | N/A | true or false | NULL|
+|not null | aaa or 2000 | NULL | true | invalid data(filtered)|
+|not null | aaa | NULL | false | NULL|
+|not null | 1 | 1 | true or false | correct data|
+
+这里以列类型为 Decimal(1,0) 举例
+
+>注:当表中的列允许导入空值时
+
+|source data | source data example | string to int | strict_mode | result|
+|------------|---------------------|-----------------|--------------------|--------|
+|空值 | \N | N/A | true or false | NULL|
+|not null | aaa | NULL | true | invalid data(filtered)|
+|not null | aaa | NULL | false | NULL|
+|not null | 1 or 10 | 1 | true or false | correct data|
+
+> 注意:10 虽然是一个超过范围的值,但是因为其类型符合 decimal的要求,所以 strict mode对其不产生影响。10 最后会在其他 ETL 处理流程中被过滤。但不会被 strict mode 过滤。
+
+#### Broker 参数
+
+Broker Load 需要借助 Broker 进程访问远端存储,不同的 Broker 需要提供不同的参数,具体请参阅 [Broker文档](../broker.md)
+
+### 查看导入
+
+Broker load 导入方式由于是异步的,所以用户必须将创建导入的 Label 记录,并且在**查看导入命令中使用 Label 来查看导入结果**。查看导入命令在所有导入方式中是通用的,具体语法可执行 ```HELP SHOW LOAD``` 查看。
+
+示例:
+
+```
+mysql> show load order by createtime desc limit 1\G
+*************************** 1. row ***************************
+ JobId: 76391
+ Label: label1
+ State: FINISHED
+ Progress: ETL:N/A; LOAD:100%
+ Type: BROKER
+ EtlInfo: unselected.rows=4; dpp.abnorm.ALL=15; dpp.norm.ALL=28133376
+ TaskInfo: cluster:N/A; timeout(s):10800; max_filter_ratio:5.0E-5
+ ErrorMsg: N/A
+ CreateTime: 2019-07-27 11:46:42
+ EtlStartTime: 2019-07-27 11:46:44
+ EtlFinishTime: 2019-07-27 11:46:44
+ LoadStartTime: 2019-07-27 11:46:44
+LoadFinishTime: 2019-07-27 11:50:16
+ URL: http://192.168.1.1:8040/api/_load_error_log?file=__shard_4/error_log_insert_stmt_4bb00753932c491a-a6da6e2725415317_4bb00753932c491a_a6da6e2725415317
+ JobDetails: {"Unfinished backends":{"9c3441027ff948a0-8287923329a2b6a7":[10002]},"ScannedRows":2390016,"TaskNumber":1,"All backends":{"9c3441027ff948a0-8287923329a2b6a7":[10002]},"FileNumber":1,"FileSize":1073741824}
+```
+
+下面主要介绍了查看导入命令返回结果集中参数意义:
+
++ JobId
+
+ 导入任务的唯一ID,每个导入任务的 JobId 都不同,由系统自动生成。与 Label 不同的是,JobId永远不会相同,而 Label 则可以在导入任务失败后被复用。
+
++ Label
+
+ 导入任务的标识。
+
++ State
+
+ 导入任务当前所处的阶段。在 Broker load 导入过程中主要会出现 PENDING 和 LOADING 这两个导入中的状态。如果 Broker load 处于 PENDING 状态,则说明当前导入任务正在等待被执行;LOADING 状态则表示正在执行中。
+
+ 导入任务的最终阶段有两个:CANCELLED 和 FINISHED,当 Load job 处于这两个阶段时,导入完成。其中 CANCELLED 为导入失败,FINISHED 为导入成功。
+
++ Progress
+
+ 导入任务的进度描述。分为两种进度:ETL 和 LOAD,对应了导入流程的两个阶段 ETL 和 LOADING。目前 Broker load 由于只有 LOADING 阶段,所以 ETL 则会永远显示为 `N/A`
+
+ LOAD 的进度范围为:0~100%。
+
+ ```LOAD 进度 = 当前完成导入的表个数 / 本次导入任务设计的总表个数 * 100%```
+
+ **如果所有导入表均完成导入,此时 LOAD 的进度为 99%** 导入进入到最后生效阶段,整个导入完成后,LOAD 的进度才会改为 100%。
+
+ 导入进度并不是线性的。所以如果一段时间内进度没有变化,并不代表导入没有在执行。
+
++ Type
+
+ 导入任务的类型。Broker load 的 type 取值只有 BROKER。
+
++ EtlInfo
+
+ 主要显示了导入的数据量指标 ```unselected.rows``` , ```dpp.norm.ALL``` 和 ```dpp.abnorm.ALL```。用户可以根据第一个数值判断 where 条件过滤了多少行,后两个指标验证当前导入任务的错误率是否超过 ```max_filter_ratio```。
+
+ 三个指标之和就是原始数据量的总行数。
+
++ TaskInfo
+
+ 主要显示了当前导入任务参数,也就是创建 Broker load 导入任务时用户指定的导入任务参数,包括:`cluster`,`timeout` 和`max_filter_ratio`。
+
++ ErrorMsg
+
+ 在导入任务状态为CANCELLED,会显示失败的原因,显示分两部分:type 和 msg,如果导入任务成功则显示 ```N/A```。
+
+ type的取值意义:
+
+ ```
+ USER_CANCEL: 用户取消的任务
+ ETL_RUN_FAIL:在ETL阶段失败的导入任务
+ ETL_QUALITY_UNSATISFIED:数据质量不合格,也就是错误数据率超过了 max_filter_ratio
+ LOAD_RUN_FAIL:在LOADING阶段失败的导入任务
+ TIMEOUT:导入任务没在超时时间内完成
+ UNKNOWN:未知的导入错误
+ ```
+
++ CreateTime/EtlStartTime/EtlFinishTime/LoadStartTime/LoadFinishTime
+
+ 这几个值分别代表导入创建的时间,ETL阶段开始的时间,ETL阶段完成的时间,Loading阶段开始的时间和整个导入任务完成的时间。
+
+ Broker load 导入由于没有 ETL 阶段,所以其 EtlStartTime, EtlFinishTime, LoadStartTime 被设置为同一个值。
+
+ 导入任务长时间停留在 CreateTime,而 LoadStartTime 为 N/A 则说明目前导入任务堆积严重。用户可减少导入提交的频率。
+
+ ```
+ LoadFinishTime - CreateTime = 整个导入任务所消耗时间
+ LoadFinishTime - LoadStartTime = 整个 Broker load 导入任务执行时间 = 整个导入任务所消耗时间 - 导入任务等待的时间
+ ```
+
++ URL
+
+ 导入任务的错误数据样例,访问 URL 地址既可获取本次导入的错误数据样例。当本次导入不存在错误数据时,URL 字段则为 N/A。
+
++ JobDetails
+
+ 显示一些作业的详细运行状态。包括导入文件的个数、总大小(字节)、子任务个数、已处理的原始行数,运行子任务的 BE 节点 Id,未完成的 BE 节点 Id。
+
+ ```
+ {"Unfinished backends":{"9c3441027ff948a0-8287923329a2b6a7":[10002]},"ScannedRows":2390016,"TaskNumber":1,"All backends":{"9c3441027ff948a0-8287923329a2b6a7":[10002]},"FileNumber":1,"FileSize":1073741824}
+ ```
+
+ 其中已处理的原始行数,每 5 秒更新一次。该行数仅用于展示当前的进度,不代表最终实际的处理行数。实际处理行数以 EtlInfo 中显示的为准。
+
+### 取消导入
+
+当 Broker load 作业状态不为 CANCELLED 或 FINISHED 时,可以被用户手动取消。取消时需要指定待取消导入任务的 Label 。取消导入命令语法可执行 ```HELP CANCEL LOAD```查看。
+
+## 相关系统配置
+
+### FE 配置
+
+下面几个配置属于 Broker load 的系统级别配置,也就是作用于所有 Broker load 导入任务的配置。主要通过修改 ``` fe.conf```来调整配置值。
+
++ min\_bytes\_per\_broker\_scanner/max\_bytes\_per\_broker\_scanner/max\_broker\_concurrency
+
+ 前两个配置限制了单个 BE 处理的数据量的最小和最大值。第三个配置限制了一个作业的最大的导入并发数。最小处理的数据量,最大并发数,源文件的大小和当前集群 BE 的个数 **共同决定了本次导入的并发数**。
+
+ ```
+ 本次导入并发数 = Math.min(源文件大小/最小处理量,最大并发数,当前BE节点个数)
+ 本次导入单个BE的处理量 = 源文件大小/本次导入的并发数
+ ```
+
+ 通常一个导入作业支持的最大数据量为 `max_bytes_per_broker_scanner * BE 节点数`。如果需要导入更大数据量,则需要适当调整 `max_bytes_per_broker_scanner` 参数的大小。
+
+ 默认配置:
+
+ ```
+ 参数名:min_bytes_per_broker_scanner, 默认 64MB,单位bytes。
+ 参数名:max_broker_concurrency, 默认 10。
+ 参数名:max_bytes_per_broker_scanner,默认 3G,单位bytes。
+ ```
+
+## 最佳实践
+
+### 应用场景
+
+使用 Broker load 最适合的场景就是原始数据在文件系统(HDFS,BOS,AFS)中的场景。其次,由于 Broker load 是单次导入中唯一的一种异步导入的方式,所以如果用户在导入大文件中,需要使用异步接入,也可以考虑使用 Broker load。
+
+### 数据量
+
+这里仅讨论单个 BE 的情况,如果用户集群有多个 BE 则下面标题中的数据量应该乘以 BE 个数来计算。比如:如果用户有3个 BE,则 3G 以下(包含)则应该乘以 3,也就是 9G 以下(包含)。
+
++ 3G 以下(包含)
+
+ 用户可以直接提交 Broker load 创建导入请求。
+
++ 3G 以上
+
+ 由于单个导入 BE 最大的处理量为 3G,超过 3G 的待导入文件就需要通过调整 Broker load 的导入参数来实现大文件的导入。
+
+ 1. 根据当前 BE 的个数和原始文件的大小修改单个 BE 的最大扫描量和最大并发数。
+
+ ```
+ 修改 fe.conf 中配置
+
+ max_broker_concurrency = BE 个数
+ 当前导入任务单个 BE 处理的数据量 = 原始文件大小 / max_broker_concurrency
+ max_bytes_per_broker_scanner >= 当前导入任务单个 BE 处理的数据量
+
+ 比如一个 100G 的文件,集群的 BE 个数为 10 个
+ max_broker_concurrency = 10
+ max_bytes_per_broker_scanner >= 10G = 100G / 10
+
+ ```
+
+ 修改后,所有的 BE 会并发的处理导入任务,每个 BE 处理原始文件的一部分。
+
+ *注意:上述两个 FE 中的配置均为系统配置,也就是说其修改是作用于所有的 Broker load的任务的。*
+
+ 2. 在创建导入的时候自定义当前导入任务的 timeout 时间
+
+ ```
+ 当前导入任务单个 BE 处理的数据量 / 用户 Doris 集群最慢导入速度(MB/s) >= 当前导入任务的 timeout 时间 >= 当前导入任务单个 BE 处理的数据量 / 10M/s
+
+ 比如一个 100G 的文件,集群的 BE 个数为 10个
+ timeout >= 1000s = 10G / 10M/s
+
+ ```
+
+ 3. 当用户发现第二步计算出的 timeout 时间超过系统默认的导入最大超时时间 4小时
+
+ 这时候不推荐用户将导入最大超时时间直接改大来解决问题。单个导入时间如果超过默认的导入最大超时时间4小时,最好是通过切分待导入文件并且分多次导入来解决问题。主要原因是:单次导入超过4小时的话,导入失败后重试的时间成本很高。
+
+ 可以通过如下公式计算出 Doris 集群期望最大导入文件数据量:
+
+ ```
+ 期望最大导入文件数据量 = 14400s * 10M/s * BE 个数
+ 比如:集群的 BE 个数为 10个
+ 期望最大导入文件数据量 = 14400s * 10M/s * 10 = 1440000M ≈ 1440G
+
+ 注意:一般用户的环境可能达不到 10M/s 的速度,所以建议超过 500G 的文件都进行文件切分,再导入。
+
+ ```
+
+### 完整例子
+
+数据情况:用户数据在 HDFS 中,文件地址为 hdfs://abc.com:8888/store_sales, hdfs 的认证用户名为 root, 密码为 password, 数据量大小约为 30G,希望导入到数据库 bj_sales 的表 store_sales 中。
+
+集群情况:集群的 BE 个数约为 3 个,Broker 名称均为 broker。
+
++ step1: 经过上述方法的计算,本次导入的单个 BE 导入量为 10G,则需要先修改 FE 的配置,将单个 BE 导入最大量修改为:
+
+ ```
+ max_bytes_per_broker_scanner = 10737418240
+
+ ```
+
++ step2: 经计算,本次导入的时间大约为 1000s,并未超过默认超时时间,可不配置导入自定义超时时间。
+
++ step3:创建导入语句
+
+ ```
+ LOAD LABEL bj_sales.store_sales_broker_load_01
+ (
+ DATA INFILE("hdfs://abc.com:8888/store_sales")
+ INTO TABLE store_sales
+ )
+ WITH BROKER 'broker'
+ ("username"="root", "password"="password");
+ ```
+
+## 常见问题
+
+* 导入报错:`Scan bytes per broker scanner exceed limit:xxx`
+
+ 请参照文档中最佳实践部分,修改 FE 配置项 `max_bytes_per_broker_scanner` 和 `max_broker_concurrency`
+
+* 导入报错:`failed to send batch` 或 `TabletWriter add batch with unknown id`
+
+ 请参照 [导入手册](./load-manual.md) 中 **通用系统配置** 中 **BE 配置**,适当修改 `query_timeout` 和 `streaming_load_rpc_max_alive_time_sec`。
+
+* 导入报错:`LOAD_RUN_FAIL; msg:Invalid Column Name:xxx`
+
+ 如果是PARQUET或者ORC格式的数据,需要再文件头的列名与doris表中的列名一致,如 :
+ ```
+ (tmp_c1,tmp_c2)
+ SET
+ (
+ id=tmp_c2,
+ name=tmp_c1
+ )
+ ```
+ 代表获取在parquet或orc中以(tmp_c1, tmp_c2)为列名的列,映射到doris表中的(id, name)列。如果没有设置set, 则以column中的列作为映射。
+
+ 注:如果使用某些hive版本直接生成的orc文件,orc文件中的表头并非hive meta数据,而是(_col0, _col1, _col2, ...), 可能导致Invalid Column Name错误,那么则需要使用set进行映射
+
diff --git a/docs/zh-CN/administrator-guide/load-data/delete-manual.md b/docs/zh-CN/administrator-guide/load-data/delete-manual.md
new file mode 100644
index 00000000000000..fd123cc12626cf
--- /dev/null
+++ b/docs/zh-CN/administrator-guide/load-data/delete-manual.md
@@ -0,0 +1,183 @@
+---
+{
+ "title": "Delete",
+ "language": "zh-CN"
+}
+---
+
+
+
+# Delete
+
+Delete不同于其他导入方式,它是一个同步过程。和Insert into相似,所有的Delete操作在Doris中是一个独立的导入作业,一般Delete语句需要指定表和分区以及删除的条件来筛选要删除的数据,并将会同时删除base表和rollup表的数据。
+
+## 语法
+
+主要的Delete语法如下:
+
+```
+DELETE FROM table_name [PARTITION partition_name]
+WHERE
+column_name1 op value[ AND column_name2 op value ...];
+```
+
+示例1:
+
+```
+DELETE FROM my_table PARTITION p1 WHERE k1 = 3;
+```
+
+示例2:
+
+```
+DELETE FROM my_table PARTITION p1 WHERE k1 < 3 AND k2 = "abc";
+```
+
+下面介绍删除语句中使用到的参数:
+
+* PARTITION
+
+ Delete语句的目标分区,若未指定,则此表必须为单分区表,否则无法delete
+
+* WHERE
+
+ Delete语句的条件语句,所有删除语句都必须指定WHERE语句
+
+说明:
+
+1. `Where`语句中的op的类型可包括`=,>,<,>=,<=,!=`,目前暂时不支持 where key in (value1, value2, value3) 的方式选定范围,后续将加上此功能。
+2. `Where`语句中的列只能是`key`列
+3. 当选定的`key`列不存在某个rollup表内时,无法进行delete
+4. 条件语句中各个条件只能是`and`关系,如希望达成`or`可将条件分别写入两个delete语句中
+5. 如果指定表为RANGE分区表,则必须指定 `PARTITION`。如果是单分区表,可以不指定。
+6. 不同于Insert into命令,delete不能手动指定`label`,有关label的概念可以查看[Insert Into文档] (./insert-into-manual.md)
+
+## 返回结果
+
+Delete命令是一个SQL命令,返回结果是同步的,分为以下几种:
+
+1. 执行成功
+
+ 如果Delete顺利执行完成并可见,将返回下列结果,`Query OK`表示成功
+
+ ```
+ mysql> delete from test_tbl PARTITION p1 where k1 = 1;
+ Query OK, 0 rows affected (0.04 sec)
+ {'label':'delete_e7830c72-eb14-4cb9-bbb6-eebd4511d251', 'status':'VISIBLE', 'txnId':'4005'}
+ ```
+
+2. 提交成功,但未可见
+
+ Doris的事务提交分为两步:提交和发布版本,只有完成了发布版本步骤,结果才对用户是可见的。若已经提交成功了,那么就可以认为最终一定会发布成功,Doris会尝试在提交完后等待发布一段时间,如果超时后即使发布版本还未完成也会优先返回给用户,提示用户提交已经完成。若如果Delete已经提交并执行,但是仍未发布版本和可见,将返回下列结果
+
+ ```
+ mysql> delete from test_tbl PARTITION p1 where k1 = 1;
+ Query OK, 0 rows affected (0.04 sec)
+ {'label':'delete_e7830c72-eb14-4cb9-bbb6-eebd4511d251', 'status':'VISIBLE', 'txnId':'4005', 'err':'delete job is committed but may be taking effect later' }
+ ```
+
+ 结果会同时返回一个json字符串:
+
+ `affected rows`表示此次删除影响的行,由于Doris的删除目前是逻辑删除,因此对于这个值是恒为0。
+
+ `label`为自动生成的 label,是该导入作业的标识。每个导入作业,都有一个在单 database 内部唯一的 Label。
+
+ `status`表示数据删除是否可见,如果可见,显示`VISIBLE`,如果不可见,显示`COMMITTED`。
+
+ `txnId`为这个Delete job对应的事务id
+
+ `err`字段会显示一些本次删除的详细信息
+
+3. 提交失败,事务取消
+
+ 如果Delete语句没有提交成功,将会被Doris自动中止,返回下列结果
+
+ ```
+ mysql> delete from test_tbl partition p1 where k1 > 80;
+ ERROR 1064 (HY000): errCode = 2, detailMessage = {错误原因}
+ ```
+
+ 示例:
+
+ 比如说一个超时的删除,将会返回timeout时间和未完成的`(tablet=replica)`
+
+ ```
+ mysql> delete from test_tbl partition p1 where k1 > 80;
+ ERROR 1064 (HY000): errCode = 2, detailMessage = failed to delete replicas from job: 4005, Unfinished replicas:10000=60000, 10001=60000, 10002=60000
+ ```
+
+ **综上,对于Delete操作返回结果的正确处理逻辑为:**
+
+ 1. 如果返回结果为`ERROR 1064 (HY000)`,则表示删除失败
+
+ 2. 如果返回结果为`Query OK`,则表示删除执行成功
+
+ 1. 如果`status`为`COMMITTED`,表示数据仍不可见,用户可以稍等一段时间再用`show delete`命令查看结果
+ 2. 如果`status`为`VISIBLE`,表示数据删除成功。
+
+## 可配置项
+
+### FE配置
+
+**TIMEOUT配置**
+
+总体来说,Doris的删除作业的超时时间限制在30秒到5分钟时间内,具体时间可通过下面配置项调整
+
+* tablet\_delete\_timeout\_second
+
+ delete自身的超时时间是可受指定分区下tablet的数量弹性改变的,此项配置为平均一个tablet所贡献的timeout时间,默认值为2。
+
+ 假设此次删除所指定分区下有5个tablet,那么可提供给delete的timeout时间为10秒,由于低于最低超时时间30秒,因此最终超时时间为30秒。
+
+* load\_straggler\_wait\_second
+
+ 如果用户预估的数据量确实比较大,使得5分钟的上限不足时,用户可以通过此项调整timeout上限,默认值为300。
+
+ **TIMEOUT的具体计算规则为(秒)**
+
+ `TIMEOUT = MIN(load_straggler_wait_second, MAX(30, tablet_delete_timeout_second * tablet_num))`
+
+* query_timeout
+
+ 因为delete本身是一个SQL命令,因此删除语句也会受session限制,timeout还受Session中的`query_timeout`值影响,可以通过`SET query_timeout = xxx`来增加超时时间,单位是秒。
+
+## 查看历史记录
+
+1. 用户可以通过show delete语句查看历史上已执行完成的删除记录
+
+ 语法
+
+ ```
+ SHOW DELETE [FROM db_name]
+ ```
+
+ 示例
+
+ ```
+ mysql> show delete from test_db;
+ +-----------+---------------+---------------------+-----------------+----------+
+ | TableName | PartitionName | CreateTime | DeleteCondition | State |
+ +-----------+---------------+---------------------+-----------------+----------+
+ | empty_tbl | p3 | 2020-04-15 23:09:35 | k1 EQ "1" | FINISHED |
+ | test_tbl | p4 | 2020-04-15 23:09:53 | k1 GT "80" | FINISHED |
+ +-----------+---------------+---------------------+-----------------+----------+
+ 2 rows in set (0.00 sec)
+ ```
+
diff --git a/docs/zh-CN/administrator-guide/load-data/insert-into-manual.md b/docs/zh-CN/administrator-guide/load-data/insert-into-manual.md
new file mode 100644
index 00000000000000..1a69e5a6a4294e
--- /dev/null
+++ b/docs/zh-CN/administrator-guide/load-data/insert-into-manual.md
@@ -0,0 +1,289 @@
+---
+{
+ "title": "Insert Into",
+ "language": "zh-CN"
+}
+---
+
+
+
+# Insert Into
+
+Insert Into 语句的使用方式和 MySQL 等数据库中 Insert Into 语句的使用方式类似。但在 Doris 中,所有的数据写入都是一个独立的导入作业。所以这里将 Insert Into 也作为一种导入方式介绍。
+
+主要的 Insert Into 命令包含以下两种;
+
+* INSERT INTO tbl SELECT ...
+* INSERT INTO tbl (col1, col2, ...) VALUES (1, 2, ...), (1,3, ...);
+
+其中第二种命令仅用于 Demo,不要使用在测试或生产环境中。
+
+## 基本操作
+
+### 创建导入
+
+Insert Into 命令需要通过 MySQL 协议提交,创建导入请求会同步返回导入结果。
+
+语法:
+
+```
+INSERT INTO table_name [WITH LABEL label] [partition_info] [col_list] [query_stmt] [VALUES];
+```
+
+示例:
+
+```
+INSERT INTO tbl2 WITH LABEL label1 SELECT * FROM tbl3;
+INSERT INTO tbl1 VALUES ("qweasdzxcqweasdzxc"), ("a");
+```
+
+**注意**
+
+当需要使用 `CTE(Common Table Expressions)` 作为 insert 操作中的查询部分时,必须指定 `WITH LABEL` 和 column list 部分。示例
+
+```
+INSERT INTO tbl1 WITH LABEL label1
+WITH cte1 AS (SELECT * FROM tbl1), cte2 AS (SELECT * FROM tbl2)
+SELECT k1 FROM cte1 JOIN cte2 WHERE cte1.k1 = 1;
+
+
+INSERT INTO tbl1 (k1)
+WITH cte1 AS (SELECT * FROM tbl1), cte2 AS (SELECT * FROM tbl2)
+SELECT k1 FROM cte1 JOIN cte2 WHERE cte1.k1 = 1;
+```
+
+下面主要介绍创建导入语句中使用到的参数:
+
++ partition\_info
+
+ 导入表的目标分区,如果指定目标分区,则只会导入符合目标分区的数据。如果没有指定,则默认值为这张表的所有分区。
+
++ col\_list
+
+ 导入表的目标列,可以以任意的顺序存在。如果没有指定目标列,那么默认值是这张表的所有列。如果待表中的某个列没有存在目标列中,那么这个列需要有默认值,否则 Insert Into 就会执行失败。
+
+ 如果查询语句的结果列类型与目标列的类型不一致,那么会调用隐式类型转化,如果不能够进行转化,那么 Insert Into 语句会报语法解析错误。
+
++ query\_stmt
+
+ 通过一个查询语句,将查询语句的结果导入到 Doris 系统中的其他表。查询语句支持任意 Doris 支持的 SQL 查询语法。
+
++ VALUES
+
+ 用户可以通过 VALUES 语法插入一条或者多条数据。
+
+ *注意:VALUES 方式仅适用于导入几条数据作为导入 DEMO 的情况,完全不适用于任何测试和生产环境。Doris 系统本身也不适合单条数据导入的场景。建议使用 INSERT INTO SELECT 的方式进行批量导入。*
+
+* WITH LABEL
+
+ INSERT 操作作为一个导入任务,也可以指定一个 label。如果不指定,则系统会自动指定一个 UUID 作为 label。
+
+ 该功能需要 0.11+ 版本。
+
+ *注意:建议指定 Label 而不是由系统自动分配。如果由系统自动分配,但在 Insert Into 语句执行过程中,因网络错误导致连接断开等,则无法得知 Insert Into 是否成功。而如果指定 Label,则可以再次通过 Label 查看任务结果。*
+
+### 导入结果
+
+Insert Into 本身就是一个 SQL 命令,其返回结果会根据执行结果的不同,分为以下几种:
+
+1. 结果集为空
+
+ 如果 insert 对应 select 语句的结果集为空,则返回如下:
+
+ ```
+ mysql> insert into tbl1 select * from empty_tbl;
+ Query OK, 0 rows affected (0.02 sec)
+ ```
+
+ `Query OK` 表示执行成功。`0 rows affected` 表示没有数据被导入。
+
+2. 结果集不为空
+
+ 在结果集不为空的情况下。返回结果分为如下几种情况:
+
+ 1. Insert 执行成功并可见:
+
+ ```
+ mysql> insert into tbl1 select * from tbl2;
+ Query OK, 4 rows affected (0.38 sec)
+ {'label':'insert_8510c568-9eda-4173-9e36-6adc7d35291c', 'status':'visible', 'txnId':'4005'}
+
+ mysql> insert into tbl1 with label my_label1 select * from tbl2;
+ Query OK, 4 rows affected (0.38 sec)
+ {'label':'my_label1', 'status':'visible', 'txnId':'4005'}
+
+ mysql> insert into tbl1 select * from tbl2;
+ Query OK, 2 rows affected, 2 warnings (0.31 sec)
+ {'label':'insert_f0747f0e-7a35-46e2-affa-13a235f4020d', 'status':'visible', 'txnId':'4005'}
+
+ mysql> insert into tbl1 select * from tbl2;
+ Query OK, 2 rows affected, 2 warnings (0.31 sec)
+ {'label':'insert_f0747f0e-7a35-46e2-affa-13a235f4020d', 'status':'committed', 'txnId':'4005'}
+ ```
+
+ `Query OK` 表示执行成功。`4 rows affected` 表示总共有4行数据被导入。`2 warnings` 表示被过滤的行数。
+
+ 同时会返回一个 json 串:
+
+ ```
+ {'label':'my_label1', 'status':'visible', 'txnId':'4005'}
+ {'label':'insert_f0747f0e-7a35-46e2-affa-13a235f4020d', 'status':'committed', 'txnId':'4005'}
+ {'label':'my_label1', 'status':'visible', 'txnId':'4005', 'err':'some other error'}
+ ```
+
+ `label` 为用户指定的 label 或自动生成的 label。Label 是该 Insert Into 导入作业的标识。每个导入作业,都有一个在单 database 内部唯一的 Label。
+
+ `status` 表示导入数据是否可见。如果可见,显示 `visible`,如果不可见,显示 `committed`。
+
+ `txnId` 为这个 insert 对应的导入事务的 id。
+
+ `err` 字段会显示一些其他非预期错误。
+
+ 当需要查看被过滤的行时,用户可以通过如下语句
+
+ ```
+ show load where label="xxx";
+ ```
+
+ 返回结果中的 URL 可以用于查询错误的数据,具体见后面 **查看错误行** 小结。
+
+ **数据不可见是一个临时状态,这批数据最终是一定可见的**
+
+ 可以通过如下语句查看这批数据的可见状态:
+
+ ```
+ show transaction where id=4005;
+ ```
+
+ 返回结果中的 `TransactionStatus` 列如果为 `visible`,则表述数据可见。
+
+ 2. Insert 执行失败
+
+ 执行失败表示没有任何数据被成功导入,并返回如下:
+
+ ```
+ mysql> insert into tbl1 select * from tbl2 where k1 = "a";
+ ERROR 1064 (HY000): all partitions have no load data. url: http://10.74.167.16:8042/api/_load_error_log?file=__shard_2/error_log_insert_stmt_ba8bb9e158e4879-ae8de8507c0bf8a2_ba8bb9e158e4879_ae8de8507c0bf8a2
+ ```
+
+ 其中 `ERROR 1064 (HY000): all partitions have no load data` 显示失败原因。后面的 url 可以用于查询错误的数据,具体见后面 **查看错误行** 小结。
+
+
+**综上,对于 insert 操作返回结果的正确处理逻辑应为:**
+
+1. 如果返回结果为 `ERROR 1064 (HY000)`,则表示导入失败。
+2. 如果返回结果为 `Query OK`,则表示执行成功。
+ 1. 如果 `rows affected` 为 0,表示结果集为空,没有数据被导入。
+ 2. 如果 `rows affected` 大于 0:
+ 1. 如果 `status` 为 `committed`,表示数据还不可见。需要通过 `show transaction` 语句查看状态直到 `visible`
+ 2. 如果 `status` 为 `visible`,表示数据导入成功。
+ 3. 如果 `warnings` 大于 0,表示有数据被过滤,可以通过 `show load` 语句获取 url 查看被过滤的行。
+
+## 相关系统配置
+
+### FE 配置
+
++ timeout
+
+ 导入任务的超时时间(以秒为单位),导入任务在设定的 timeout 时间内未完成则会被系统取消,变成 CANCELLED。
+
+ 目前 Insert Into 并不支持自定义导入的 timeout 时间,所有 Insert Into 导入的超时时间是统一的,默认的 timeout 时间为1小时。如果导入的源文件无法再规定时间内完成导入,则需要调整 FE 的参数```insert_load_default_timeout_second```。
+
+ 同时 Insert Into 语句收到 Session 变量 `query_timeout` 的限制。可以通过 `SET query_timeout = xxx;` 来增加超时时间,单位是秒。
+
+### Session 变量
+
++ enable\_insert\_strict
+
+ Insert Into 导入本身不能控制导入可容忍的错误率。用户只能通过 `enable_insert_strict` 这个 Session 参数用来控制。
+
+ 当该参数设置为 false 时,表示至少有一条数据被正确导入,则返回成功。如果有失败数据,则还会返回一个 Label。
+
+ 当该参数设置为 true 时,表示如果有一条数据错误,则导入失败。
+
+ 默认为 false。可通过 `SET enable_insert_strict = true;` 来设置。
+
++ query\_timeout
+
+ Insert Into 本身也是一个 SQL 命令,因此 Insert Into 语句也受到 Session 变量 `query_timeout` 的限制。可以通过 `SET query_timeout = xxx;` 来增加超时时间,单位是秒。
+
+## 最佳实践
+
+### 应用场景
+1. 用户希望仅导入几条假数据,验证一下 Doris 系统的功能。此时适合使用 INSERT INTO VALUS 的语法。
+2. 用户希望将已经在 Doris 表中的数据进行 ETL 转换并导入到一个新的 Doris 表中,此时适合使用 INSERT INTO SELECT 语法。
+3. 用户可以创建一种外部表,如 MySQL 外部表映射一张 MySQL 系统中的表。或者创建 Broker 外部表来映射 HDFS 上的数据文件。然后通过 INSERT INTO SELECT 语法将外部表中的数据导入到 Doris 表中存储。
+
+### 数据量
+Insert Into 对数据量没有限制,大数据量导入也可以支持。但 Insert Into 有默认的超时时间,用户预估的导入数据量过大,就需要修改系统的 Insert Into 导入超时时间。
+
+```
+导入数据量 = 36G 约≤ 3600s * 10M/s
+其中 10M/s 是最大导入限速,用户需要根据当前集群情况计算出平均的导入速度来替换公式中的 10M/s
+```
+
+### 完整例子
+
+用户有一张表 store\_sales 在数据库 sales 中,用户又创建了一张表叫 bj\_store\_sales 也在数据库 sales 中,用户希望将 store\_sales 中销售记录在 bj 的数据导入到这张新建的表 bj\_store\_sales 中。导入的数据量约为:10G。
+
+```
+store_sales schema:
+(id, total, user_id, sale_timestamp, region)
+
+bj_store_sales schema:
+(id, total, user_id, sale_timestamp)
+
+```
+
+集群情况:用户当前集群的平均导入速度约为 5M/s
+
++ Step1: 判断是否要修改 Insert Into 的默认超时时间
+
+ ```
+ 计算导入的大概时间
+ 10G / 5M/s = 2000s
+
+ 修改 FE 配置
+ insert_load_default_timeout_second = 2000
+ ```
+
++ Step2:创建导入任务
+
+ 由于用户是希望将一张表中的数据做 ETL 并导入到目标表中,所以应该使用 Insert into query\_stmt 方式导入。
+
+ ```
+ INSERT INTO bj_store_sales WITH LABEL `label` SELECT id, total, user_id, sale_timestamp FROM store_sales where region = "bj";
+ ```
+
+## 常见问题
+
+* 查看错误行
+
+ 由于 Insert Into 无法控制错误率,只能通过 `enable_insert_strict` 设置为完全容忍错误数据或完全忽略错误数据。因此如果 `enable_insert_strict` 设为 true,则 Insert Into 可能会失败。而如果 `enable_insert_strict` 设为 false,则可能出现仅导入了部分合格数据的情况。
+
+ 当返回结果中提供了 url 字段时,可以通过以下命令查看错误行:
+
+ ```SHOW LOAD WARNINGS ON "url";```
+
+ 示例:
+
+ ```SHOW LOAD WARNINGS ON "http://ip:port/api/_load_error_log?file=__shard_13/error_log_insert_stmt_d2cac0a0a16d482d-9041c949a4b71605_d2cac0a0a16d482d_9041c949a4b71605";```
+
+ 错误的原因通常如:源数据列长度超过目的数据列长度、列类型不匹配、分区不匹配、列顺序不匹配等等。
diff --git a/docs/zh-CN/administrator-guide/load-data/load-manual.md b/docs/zh-CN/administrator-guide/load-data/load-manual.md
new file mode 100644
index 00000000000000..fe0de251f832ee
--- /dev/null
+++ b/docs/zh-CN/administrator-guide/load-data/load-manual.md
@@ -0,0 +1,217 @@
+---
+{
+ "title": "导入总览",
+ "language": "zh-CN"
+}
+---
+
+
+
+# 导入总览
+
+导入(Load)功能就是将用户的原始数据导入到 Doris 中。导入成功后,用户即可通过 Mysql 客户端查询数据。
+
+Doris 支持多种导入方式。建议先完整阅读本文档,再根据所选择的导入方式,查看各自导入方式的详细文档。
+
+## 基本概念
+
+1. Frontend(FE):Doris 系统的元数据和调度节点。在导入流程中主要负责导入规划生成和导入任务的调度工作。
+2. Backend(BE):Doris 系统的计算和存储节点。在导入流程中主要负责数据的 ETL 和存储。
+3. Broker:Broker 为一个独立的无状态进程。封装了文件系统接口,提供 Doris 读取远端存储系统中文件的能力。
+4. 导入作业(Load job):导入作业读取用户提交的源数据,转换或清洗后,将数据导入到 Doris 系统中。导入完成后,数据即可被用户查询到。
+5. Label:所有导入作业都有一个 Label。Label 在一个数据库内唯一,可由用户指定或系统自动生成,用于标识一个导入作业。相同的 Label 仅可用于一个成功的导入作业。
+6. MySQL 协议/HTTP 协议:Doris 提供两种访问协议接口。 MySQL 协议和 HTTP 协议。部分导入方式使用 MySQL 协议接口提交作业,部分导入方式使用 HTTP 协议接口提交作业。
+
+## 导入方式
+
+为适配不同的数据导入需求,Doris 系统提供了5种不同的导入方式。每种导入方式支持不同的数据源,存在不同的使用方式(异步,同步)。
+
+所有导入方式都支持 csv 数据格式。其中 Broker load 还支持 parquet 和 orc 数据格式。
+
+每个导入方式的说明请参阅单个导入方式的操作手册。
+
+* Broker load
+
+ 通过 Broker 进程访问并读取外部数据源(如 HDFS)导入到 Doris。用户通过 Mysql 协议提交导入作业后,异步执行。通过 `SHOW LOAD` 命令查看导入结果。
+
+* Stream load
+
+ 用户通过 HTTP 协议提交请求并携带原始数据创建导入。主要用于快速将本地文件或数据流中的数据导入到 Doris。导入命令同步返回导入结果。
+
+* Insert
+
+ 类似 MySQL 中的 Insert 语句,Doris 提供 `INSERT INTO tbl SELECT ...;` 的方式从 Doris 的表中读取数据并导入到另一张表。或者通过 `INSERT INTO tbl VALUES(...);` 插入单条数据。
+
+* Multi load
+
+ 用户通过 HTTP 协议提交多个导入作业。Multi Load 可以保证多个导入作业的原子生效。
+
+* Routine load
+
+ 用户通过 MySQL 协议提交例行导入作业,生成一个常驻线程,不间断的从数据源(如 Kafka)中读取数据并导入到 Doris 中。
+
+## 基本原理
+
+### 导入执行流程
+
+```
++---------+ +---------+ +----------+ +-----------+
+| | | | | | | |
+| PENDING +----->+ ETL +----->+ LOADING +----->+ FINISHED |
+| | | | | | | |
++---------+ +---+-----+ +----+-----+ +-----------+
+ | | |
+ | | |
+ | | |
+ | | | +-----------+
+ | | | | |
+ +---------------+-----------------+------------> CANCELLED |
+ | |
+ +-----------+
+
+```
+
+如上图,一个导入作业主要经过上面4个阶段。
+
++ PENDING(非必须): 该阶段只有 Broker Load 才有。Broker Load 被用户提交后会短暂停留在这个阶段,直到被 FE 中的 Scheduler 调度。 其中 Scheduler 的调度间隔为5秒。
+
++ ETL(非必须): 该阶段在版本 0.10.0(包含) 之前存在,主要是用于将原始数据按照用户声明的方式进行变换,并且过滤不满足条件的原始数据。在 0.10.0 后的版本,ETL 阶段不再存在,其中数据 transform 的工作被合并到 LOADING 阶段。
+
++ LOADING: 该阶段在版本 0.10.0(包含)之前主要用于将变换后的数据推到对应的 BE 存储中。在 0.10.0 后的版本,该阶段先对数据进行清洗和变换,然后将数据发送到 BE 存储中。当所有导入数据均完成导入后,进入等待生效过程,此时 Load job 依旧是 LOADING。
+
++ FINISHED: 在 Load job 涉及的所有数据均生效后,Load job 的状态变成 FINISHED。FINISHED 后导入的数据均可查询。
+
++ CANCELLED: 在作业 FINISH 的之前,作业都可能被取消并进入 CANCELLED 状态。如用户手动取消,或导入出现错误等。CANCELLED 也是 Load Job 的最终状态,不可被再次执行。
+
+上述阶段,除了 PENDING 到 LOADING 阶段是 Scheduler 轮训调度的,其他阶段之前的转移都是回调机制实现。
+
+### Label 和 原子性
+
+Doris 对所有导入方式提供原子性保证。既保证同一个导入作业内的数据,原子生效。不会出现仅导入部分数据的情况。
+
+同时,每一个导入作业都有一个由用户指定或者系统自动生成的 Label。Label 在一个 Database 内唯一。当一个 Label 对应的导入作业成功后,不可再重复使用该 Label 提交导入作业。如果 Label 对应的导入作业失败,则可以重复使用。
+
+用户可以通过 Label 机制,来保证 Label 对应的数据最多被导入一次,即At-Most-Once 语义。
+
+## 同步和异步
+
+Doris 目前的导入方式分为两类,同步和异步。如果是外部程序接入 Doris 的导入功能,需要判断使用导入方式是哪类再确定接入逻辑。
+
+### 同步
+
+同步导入方式即用户创建导入任务,Doris 同步执行导入,执行完成后返回用户导入结果。用户可直接根据创建导入任务命令返回的结果同步判断导入是否成功。
+
+同步类型的导入方式有: **Stream load**,**Insert**。
+
+操作步骤:
+
+1. 用户(外部系统)创建导入任务。
+2. Doris 返回导入结果。
+3. 用户(外部系统)判断导入结果,如果失败可以再次提交导入任务。
+
+*注意:如果用户使用的导入方式是同步返回的,且导入的数据量过大,则创建导入请求可能会花很长时间才能返回结果。*
+
+### 异步
+异步导入方式即用户创建导入任务后,Doris 直接返回创建成功。**创建成功不代表数据已经导入**。导入任务会被异步执行,用户在创建成功后,需要通过轮询的方式发送查看命令查看导入作业的状态。如果创建失败,则可以根据失败信息,判断是否需要再次创建。
+
+异步类型的导入方式有:**Broker load**,**Multi load**。
+
+操作步骤:
+
+1. 用户(外部系统)创建导入任务。
+2. Doris 返回导入创建结果。
+3. 用户(外部系统)判断导入创建结果,成功则进入4,失败回到重试创建导入,回到1。
+4. 用户(外部系统)轮询查看导入任务,直到状态变为 FINISHED 或 CANCELLED。
+
+### 注意事项
+无论是异步还是同步的导入类型,都不应该在 Doris 返回导入失败或导入创建失败后,无休止的重试。**外部系统在有限次数重试并失败后,保留失败信息,大部分多次重试均失败问题都是使用方法问题或数据本身问题。**
+
+## 内存限制
+
+用户可以通过设置参数来限制单个导入的内存使用,以防止导入占用过多的内存而导致系统OOM。
+不同导入方式限制内存的方式略有不同,可以参阅各自的导入手册查看。
+
+一个导入作业通常会分布在多个 Backend 上执行,导入内存限制的是一个导入作业,在单个 Backend 上的内存使用,而不是在整个集群的内存使用。
+
+同时,每个 Backend 会设置可用于导入的内存的总体上限。具体配置参阅下面的通用系统配置小节。这个配置限制了所有在该 Backend 上运行的导入任务的总体内存使用上限。
+
+较小的内存限制可能会影响导入效率,因为导入流程可能会因为内存达到上限而频繁的将内存中的数据写回磁盘。而过大的内存限制可能导致当导入并发较高时,系统OOM。所以,需要根据需求,合理的设置导入的内存限制。
+
+## 最佳实践
+
+用户在接入 Doris 导入时,一般会采用程序接入的方式,这样可以保证数据被定期的导入到 Doris 中。下面主要说明了程序接入 Doris 的最佳实践。
+
+1. 选择合适的导入方式:根据数据源所在位置选择导入方式。例如:如果原始数据存放在 HDFS 上,则使用 Broker load 导入。
+2. 确定导入方式的协议:如果选择了 Broker load 导入方式,则外部系统需要能使用 MySQL 协议定期提交和查看导入作业。
+3. 确定导入方式的类型:导入方式为同步或异步。比如 Broker load 为异步导入方式,则外部系统在提交创建导入后,必须调用查看导入命令,根据查看导入命令的结果来判断导入是否成功。
+4. 制定 Label 生成策略:Label 生成策略需满足,每一批次数据唯一且固定的原则。这样 Doris 就可以保证 At-Most-Once。
+5. 程序自身保证 At-Least-Once:外部系统需要保证自身的 At-Least-Once,这样就可以保证导入流程的 Exactly-Once。
+
+## 通用系统配置
+
+下面主要解释了几个所有导入方式均通用的系统级别的配置。
+
+### FE 配置
+
+以下配置属于 FE 的系统配置,可以通过修改 FE 的配置文件 ```fe.conf``` 来修改配置。
+
++ max\_load\_timeout\_second 和 min\_load\_timeout\_second
+
+ 这两个配置含义为:最大的导入超时时间,最小的导入超时时间,以秒为单位。默认的最大超时时间为3天, 默认的最小超时时间为1秒。用户自定义的导入超时时间不可超过这个范围。该参数通用于所有的导入方式。
+
++ desired\_max\_waiting\_jobs
+
+ 在等待队列中的导入任务个数最大值,默认为100。当在 FE 中处于 PENDING 状态(也就是等待执行的)导入个数超过该值,新的导入请求则会被拒绝。
+
+ 此配置仅对异步执行的导入有效,当异步执行的导入等待个数超过默认值,则后续的创建导入请求会被拒绝。
+
++ max\_running\_txn\_num\_per\_db
+
+ 这个配置的含义是说,每个 Database 中正在运行的导入最大个数(不区分导入类型,统一计数)。当当前 Database 正在运行的导入个数超过最大值时,后续的导入不会被执行。如果是同步导入作业,则导入会被拒绝。如果是异步导入作业。则作业会在队列中等待。
+
+### BE 配置
+
+以下配置属于 BE 的系统配置,可以通过修改 BE 的配置文件 ```be.conf``` 来修改配置。
+
++ push\_write\_mbytes\_per\_sec
+
+ BE 上单个 Tablet 的写入速度限制。默认是 10,即 10MB/s。通常 BE 对单个 Tablet 的最大写入速度,根据 Schema 以及系统的不同,大约在 10-30MB/s 之间。可以适当调整这个参数来控制导入速度。
+
++ write\_buffer\_size
+
+ 导入数据在 BE 上会先写入一个 memtable,memtable 达到阈值后才会写回磁盘。默认大小是 100MB。过小的阈值可能导致 BE 上存在大量的小文件。可以适当提高这个阈值减少文件数量。但过大的阈值可能导致 RPC 超时,见下面的配置说明。
+
++ tablet\_writer\_rpc\_timeout\_sec
+
+ 导入过程中,发送一个 Batch(1024行)的 RPC 超时时间。默认 600 秒。因为该 RPC 可能涉及多个 memtable 的写盘操作,所以可能会因为写盘导致 RPC 超时,可以适当调整这个超时时间来减少超时错误(如 `send batch fail` 错误)。同时,如果调大 `write_buffer_size` 配置,也需要适当调大这个参数。
+
++ streaming\_load\_rpc\_max\_alive\_time\_sec
+
+ 在导入过程中,Doris 会为每一个 Tablet 开启一个 Writer,用于接收数据并写入。这个参数指定了 Writer 的等待超时时间。如果在这个时间内,Writer 没有收到任何数据,则 Writer 会被自动销毁。当系统处理速度较慢时,Writer 可能长时间接收不到下一批数据,导致导入报错:`TabletWriter add batch with unknown id`。此时可适当增大这个配置。默认为 600 秒。
+
+* load\_process\_max\_memory\_limit\_bytes 和 load\_process\_max\_memory\_limit\_percent
+
+ 这两个参数,限制了单个 Backend 上,可用于导入任务的内存上限。分别是最大内存和最大内存百分比。`load_process_max_memory_limit_percent` 默认为 80,表示对 Backend 总内存限制的百分比(总内存限制 `mem_limit` 默认为 80%,表示对物理内存的百分比)。即假设物理内存为 M,则默认导入内存限制为 M * 80% * 80%。
+
+ `load_process_max_memory_limit_bytes` 默认为 100GB。系统会在两个参数中取较小者,作为最终的 Backend 导入内存使用上限。
+
++ label\_keep\_max\_second
+
+ 设置导入任务记录保留时间。已经完成的( FINISHED or CANCELLED )导入任务记录会保留在 Doris 系统中一段时间,时间由此参数决定。参数默认值时间为3天。该参数通用与所有类型的导入任务。
diff --git a/docs/zh-CN/administrator-guide/load-data/routine-load-manual.md b/docs/zh-CN/administrator-guide/load-data/routine-load-manual.md
new file mode 100644
index 00000000000000..3925cd89b407af
--- /dev/null
+++ b/docs/zh-CN/administrator-guide/load-data/routine-load-manual.md
@@ -0,0 +1,299 @@
+---
+{
+ "title": "Routine Load",
+ "language": "zh-CN"
+}
+---
+
+
+
+# Routine Load
+
+例行导入(Routine Load)功能为用户提供了一种自动从指定数据源进行数据导入的功能。
+
+本文档主要介绍该功能的实现原理、使用方式以及最佳实践。
+
+## 名词解释
+
+* FE:Frontend,Doris 的前端节点。负责元数据管理和请求接入。
+* BE:Backend,Doris 的后端节点。负责查询执行和数据存储。
+* RoutineLoadJob:用户提交的一个例行导入作业。
+* JobScheduler:例行导入作业调度器,用于调度和拆分一个 RoutineLoadJob 为多个 Task。
+* Task:RoutineLoadJob 被 JobScheduler 根据规则拆分的子任务。
+* TaskScheduler:任务调度器。用于调度 Task 的执行。
+
+## 原理
+
+```
+ +---------+
+ | Client |
+ +----+----+
+ |
++-----------------------------+
+| FE | |
+| +-----------v------------+ |
+| | | |
+| | Routine Load Job | |
+| | | |
+| +---+--------+--------+--+ |
+| | | | |
+| +---v--+ +---v--+ +---v--+ |
+| | task | | task | | task | |
+| +--+---+ +---+--+ +---+--+ |
+| | | | |
++-----------------------------+
+ | | |
+ v v v
+ +---+--+ +--+---+ ++-----+
+ | BE | | BE | | BE |
+ +------+ +------+ +------+
+
+```
+
+如上图,Client 向 FE 提交一个例行导入作业。
+
+FE 通过 JobScheduler 将一个导入作业拆分成若干个 Task。每个 Task 负责导入指定的一部分数据。Task 被 TaskScheduler 分配到指定的 BE 上执行。
+
+在 BE 上,一个 Task 被视为一个普通的导入任务,通过 Stream Load 的导入机制进行导入。导入完成后,向 FE 汇报。
+
+FE 中的 JobScheduler 根据汇报结果,继续生成后续新的 Task,或者对失败的 Task 进行重试。
+
+整个例行导入作业通过不断的产生新的 Task,来完成数据不间断的导入。
+
+## Kafka 例行导入
+
+当前我们仅支持从 Kafka 系统进行例行导入。该部分会详细介绍 Kafka 例行导入使用方式和最佳实践。
+
+### 使用限制
+
+1. 支持无认证的 Kafka 访问,以及通过 SSL 方式认证的 Kafka 集群。
+2. 支持的消息格式为 csv 文本格式。每一个 message 为一行,且行尾**不包含**换行符。
+3. 仅支持 Kafka 0.10.0.0(含) 以上版本。
+
+### 创建例行导入任务
+
+创建例行导入任务的的详细语法可以连接到 Doris 后,执行 `HELP ROUTINE LOAD;` 查看语法帮助。这里主要详细介绍,创建作业时的注意事项。
+
+* columns_mapping
+
+ `columns_mapping` 主要用于指定表结构和 message 中的列映射关系,以及一些列的转换。如果不指定,Doris 会默认 message 中的列和表结构的列按顺序一一对应。虽然在正常情况下,如果源数据正好一一对应,则不指定也可以进行正常的数据导入。但是我们依然强烈建议用户**显式的指定列映射关系**。这样当表结构发生变化(比如增加一个 nullable 的列),或者源文件发生变化(比如增加了一列)时,导入任务依然可以继续进行。否则,当发生上述变动后,因为列映射关系不再一一对应,导入将报错。
+
+ 在 `columns_mapping` 中我们同样可以使用一些内置函数进行列的转换。但需要注意函数参数对应的实际列类型。举例说明:
+
+ 假设用户需要导入只包含 `k1` 一列的表,列类型为 `int`。并且需要将源文件中的 null 值转换为 0。该功能可以通过 `ifnull` 函数实现。正确是的使用方式如下:
+
+ `COLUMNS (xx, k1=ifnull(xx, "3"))`
+
+ 注意这里我们使用 `"3"` 而不是 `3`,虽然 `k1` 的类型为 `int`。因为对于导入任务来说,源数据中的列类型都为 `varchar`,所以这里 `xx` 虚拟列的类型也为 `varchar`。所以我们需要使用 `"3"` 来进行对应的匹配,否则 `ifnull` 函数无法找到参数为 `(varchar, int)` 的函数签名,将出现错误。
+
+ 再举例,假设用户需要导入只包含 `k1` 一列的表,列类型为 `int`。并且需要将源文件中的对应列进行处理:将负数转换为正数,而将正数乘以 100。这个功能可以通过 `case when` 函数实现,正确写法应如下:
+
+ `COLUMNS (xx, case when xx < 0 than cast(-xx as varchar) else cast((xx + '100') as varchar) end)`
+
+ 注意这里我们需要将 `case when` 中所有的参数都最终转换为 varchar,才能得到期望的结果。
+
+* where_predicates
+
+ `where_predicates` 中的的列的类型,已经是实际的列类型了,所以无需向 `columns_mapping` 那样强制的转换为 varchar 类型。按照实际的列类型书写即可。
+
+* desired\_concurrent\_number
+
+ `desired_concurrent_number` 用于指定一个例行作业期望的并发度。即一个作业,最多有多少 task 同时在执行。对于 Kafka 导入而言,当前的实际并发度计算如下:
+
+ ```
+ Min(partition num, desired_concurrent_number, alive_backend_num, Config.max_routine_load_task_concurrrent_num)
+ ```
+
+ 其中 `Config.max_routine_load_task_concurrrent_num` 是系统的一个默认的最大并发数限制。这是一个 FE 配置,可以通过改配置调整。默认为 5。
+
+ 其中 partition num 指订阅的 Kafka topic 的 partition 数量。`alive_backend_num` 是当前正常的 BE 节点数。
+
+* max\_batch\_interval/max\_batch\_rows/max\_batch\_size
+
+ 这三个参数用于控制单个任务的执行时间。其中任意一个阈值达到,则任务结束。其中 `max_batch_rows` 用于记录从 Kafka 中读取到的数据行数。`max_batch_size` 用于记录从 Kafka 中读取到的数据量,单位是字节。目前一个任务的消费速率大约为 5-10MB/s。
+
+ 那么假设一行数据 500B,用户希望每 100MB 或 10 秒为一个 task。100MB 的预期处理时间是 10-20 秒,对应的行数约为 200000 行。则一个合理的配置为:
+
+ ```
+ "max_batch_interval" = "10",
+ "max_batch_rows" = "200000",
+ "max_batch_size" = "104857600"
+ ```
+
+ 以上示例中的参数也是这些配置的默认参数。
+
+* max\_error\_number
+
+ `max_error_number` 用于控制错误率。在错误率过高的时候,作业会自动暂停。因为整个作业是面向数据流的,且由于数据流的无边界性,我们无法像其他导入任务一样,通过一个错误比例来计算错误率。因此这里提供了一种新的计算方式,来计算数据流中的错误比例。
+
+ 我们设定了一个采样窗口。窗口的大小为 `max_batch_rows * 10`。在一个采样窗口内,如果错误行数超过 `max_error_number`,则作业被暂停。如果没有超过,则下一个窗口重新开始计算错误行数。
+
+ 我们假设 `max_batch_rows` 为 200000,则窗口大小为 2000000。设 `max_error_number` 为 20000,即用户预期每 2000000 行的错误行为 20000。即错误率为 1%。但是因为不是每批次任务正好消费 200000 行,所以窗口的实际范围是 [2000000, 2200000],即有 10% 的统计误差。
+
+ 错误行不包括通过 where 条件过滤掉的行。但是包括没有对应的 Doris 表中的分区的行。
+
+* data\_source\_properties
+
+ `data_source_properties` 中可以指定消费具体的 Kakfa partition。如果不指定,则默认消费所订阅的 topic 的所有 partition。
+
+ 注意,当显式的指定了 partition,则导入作业不会再动态的检测 Kafka partition 的变化。如果没有指定,则会根据 kafka partition 的变化,动态调整需要消费的 partition。
+
+* strict\_mode
+
+ Routine load 导入可以开启 strict mode 模式。开启方式为在 job\_properties 中增加 ```"strict_mode" = "true"``` 。默认的 strict mode 为关闭。
+
+ strict mode 模式的意思是:对于导入过程中的列类型转换进行严格过滤。严格过滤的策略如下:
+
+ 1. 对于列类型转换来说,如果 strict mode 为true,则错误的数据将被 filter。这里的错误数据是指:原始数据并不为空值,在参与列类型转换后结果为空值的这一类数据。
+
+ 2. 对于导入的某列由函数变换生成时,strict mode 对其不产生影响。
+
+ 3. 对于导入的某列类型包含范围限制的,如果原始数据能正常通过类型转换,但无法通过范围限制的,strict mode 对其也不产生影响。例如:如果类型是 decimal(1,0), 原始数据为 10,则属于可以通过类型转换但不在列声明的范围内。这种数据 strict 对其不产生影响。
+
+#### strict mode 与 source data 的导入关系
+
+这里以列类型为 TinyInt 来举例
+
+>注:当表中的列允许导入空值时
+
+|source data | source data example | string to int | strict_mode | result|
+|------------|---------------------|-----------------|--------------------|---------|
+|空值 | \N | N/A | true or false | NULL|
+|not null | aaa or 2000 | NULL | true | invalid data(filtered)|
+|not null | aaa | NULL | false | NULL|
+|not null | 1 | 1 | true or false | correct data|
+
+这里以列类型为 Decimal(1,0) 举例
+
+>注:当表中的列允许导入空值时
+
+|source data | source data example | string to int | strict_mode | result|
+|------------|---------------------|-----------------|--------------------|--------|
+|空值 | \N | N/A | true or false | NULL|
+|not null | aaa | NULL | true | invalid data(filtered)|
+|not null | aaa | NULL | false | NULL|
+|not null | 1 or 10 | 1 | true or false | correct data|
+
+> 注意:10 虽然是一个超过范围的值,但是因为其类型符合 decimal的要求,所以 strict mode对其不产生影响。10 最后会在其他 ETL 处理流程中被过滤。但不会被 strict mode 过滤。
+
+#### 访问 SSL 认证的 Kafka 集群
+
+访问 SSL 认证的 Kafka 集群需要用户提供用于认证 Kafka Broker 公钥的证书文件(ca.pem)。如果 Kafka 集群同时开启了客户端认证,则还需提供客户端的公钥(client.pem)、密钥文件(client.key),以及密钥密码。这里所需的文件需要先通过 `CREAE FILE` 命令上传到 Doris 中,**并且 catalog 名称为 `kafka`**。`CREATE FILE` 命令的具体帮助可以参见 `HELP CREATE FILE;`。这里给出示例:
+
+1. 上传文件
+
+ ```
+ CREATE FILE "ca.pem" PROPERTIES("url" = "https://example_url/kafka-key/ca.pem", "catalog" = "kafka");
+ CREATE FILE "client.key" PROPERTIES("url" = "https://example_urlkafka-key/client.key", "catalog" = "kafka");
+ CREATE FILE "client.pem" PROPERTIES("url" = "https://example_url/kafka-key/client.pem", "catalog" = "kafka");
+ ```
+
+2. 创建例行导入作业
+
+ ```
+ CREATE ROUTINE LOAD db1.job1 on tbl1
+ PROPERTIES
+ (
+ "desired_concurrent_number"="1"
+ )
+ FROM KAFKA
+ (
+ "kafka_broker_list"= "broker1:9091,broker2:9091",
+ "kafka_topic" = "my_topic",
+ "property.security.protocol" = "ssl",
+ "property.ssl.ca.location" = "FILE:ca.pem",
+ "property.ssl.certificate.location" = "FILE:client.pem",
+ "property.ssl.key.location" = "FILE:client.key",
+ "property.ssl.key.password" = "abcdefg"
+ );
+ ```
+
+> Doris 通过 Kafka 的 C++ API `librdkafka` 来访问 Kafka 集群。`librdkafka` 所支持的参数可以参阅
+>
+> `https://github.com/edenhill/librdkafka/blob/master/CONFIGURATION.md`
+
+
+### 查看导入作业状态
+
+查看**作业**状态的具体命令和示例可以通过 `HELP SHOW ROUTINE LOAD;` 命令查看。
+
+查看**任务**运行状态的具体命令和示例可以通过 `HELP SHOW ROUTINE LOAD TASK;` 命令查看。
+
+只能查看当前正在运行中的任务,已结束和未开始的任务无法查看。
+
+### 作业控制
+
+用户可以通过 `STOP/PAUSE/RESUME` 三个命令来控制作业的停止,暂停和重启。可以通过 `HELP STOP ROUTINE LOAD;`, `HELP PAUSE ROUTINE LOAD;` 以及 `HELP RESUME ROUTINE LOAD;` 三个命令查看帮助和示例。
+
+## 其他说明
+
+1. 例行导入作业和 ALTER TABLE 操作的关系
+
+ * 例行导入不会阻塞 SCHEMA CHANGE 和 ROLLUP 操作。但是注意如果 SCHEMA CHANGE 完成后,列映射关系无法匹配,则会导致作业的错误数据激增,最终导致作业暂停。建议通过在例行导入作业中显式指定列映射关系,以及通过增加 Nullable 列或带 Default 值的列来减少这类问题。
+ * 删除表的 Partition 可能会导致导入数据无法找到对应的 Partition,作业进入暂停。
+
+2. 例行导入作业和其他导入作业的关系(LOAD, DELETE, INSERT)
+
+ * 例行导入和其他 LOAD 作业以及 INSERT 操作没有冲突。
+ * 当执行 DELETE 操作时,对应表分区不能有任何正在执行的导入任务。所以在执行 DELETE 操作前,可能需要先暂停例行导入作业,并等待已下发的 task 全部完成后,才可以执行 DELETE。
+
+3. 例行导入作业和 DROP DATABASE/TABLE 操作的关系
+
+ 当例行导入对应的 database 或 table 被删除后,作业会自动 CANCEL。
+
+4. kafka 类型的例行导入作业和 kafka topic 的关系
+
+ 当用户在创建例行导入声明的 `kafka_topic` 在kafka集群中不存在时。
+
+ * 如果用户 kafka 集群的 broker 设置了 `auto.create.topics.enable = true`,则 `kafka_topic` 会先被自动创建,自动创建的 partition 个数是由**用户方的kafka集群**中的 broker 配置 `num.partitions` 决定的。例行作业会正常的不断读取该 topic 的数据。
+ * 如果用户 kafka 集群的 broker 设置了 `auto.create.topics.enable = false`, 则 topic 不会被自动创建,例行作业会在没有读取任何数据之前就被暂停,状态为 `PAUSED`。
+
+ 所以,如果用户希望当 kafka topic 不存在的时候,被例行作业自动创建的话,只需要将**用户方的kafka集群**中的 broker 设置 `auto.create.topics.enable = true` 即可。
+
+## 相关参数
+
+一些系统配置参数会影响例行导入的使用。
+
+1. max\_routine\_load\_task\_concurrent\_num
+
+ FE 配置项,默认为 5,可以运行时修改。该参数限制了一个例行导入作业最大的子任务并发数。建议维持默认值。设置过大,可能导致同时并发的任务数过多,占用集群资源。
+
+2. max\_routine_load\_task\_num\_per\_be
+
+ FE 配置项,默认为5,可以运行时修改。该参数限制了每个 BE 节点最多并发执行的子任务个数。建议维持默认值。如果设置过大,可能导致并发任务数过多,占用集群资源。
+
+3. max\_routine\_load\_job\_num
+
+ FE 配置项,默认为100,可以运行时修改。该参数限制的例行导入作业的总数,包括 NEED_SCHEDULED, RUNNING, PAUSE 这些状态。超过后,不能在提交新的作业。
+
+4. max\_consumer\_num\_per\_group
+
+ BE 配置项,默认为 3。该参数表示一个子任务中最多生成几个 consumer 进行数据消费。对于 Kafka 数据源,一个 consumer 可能消费一个或多个 kafka partition。假设一个任务需要消费 6 个 kafka partition,则会生成 3 个 consumer,每个 consumer 消费 2 个 partition。如果只有 2 个 partition,则只会生成 2 个 consumer,每个 consumer 消费 1 个 partition。
+
+5. push\_write\_mbytes\_per\_sec
+
+ BE 配置项。默认为 10,即 10MB/s。该参数为导入通用参数,不限于例行导入作业。该参数限制了导入数据写入磁盘的速度。对于 SSD 等高性能存储设备,可以适当增加这个限速。
+
+6. max\_tolerable\_backend\_down\_num
+ FE 配置项,默认值是0。在满足某些条件下,Doris可PAUSED的任务重新调度,即变成RUNNING。该参数为0代表只有所有BE节点是alive状态才允许重新调度。
+
+7. period\_of\_auto\_resume\_min
+ FE 配置项,默认是5分钟。Doris重新调度,只会在5分钟这个周期内,最多尝试3次. 如果3次都失败则锁定当前任务,后续不在进行调度。但可通过人为干预,进行手动恢复。
+
diff --git a/docs/zh-CN/administrator-guide/load-data/stream-load-manual.md b/docs/zh-CN/administrator-guide/load-data/stream-load-manual.md
new file mode 100644
index 00000000000000..345eb357a7764c
--- /dev/null
+++ b/docs/zh-CN/administrator-guide/load-data/stream-load-manual.md
@@ -0,0 +1,337 @@
+---
+{
+ "title": "Stream load",
+ "language": "zh-CN"
+}
+---
+
+
+
+# Stream load
+
+Stream load 是一个同步的导入方式,用户通过发送 HTTP 协议发送请求将本地文件或数据流导入到 Doris 中。Stream load 同步执行导入并返回导入结果。用户可直接通过请求的返回体判断本次导入是否成功。
+
+Stream load 主要适用于导入本地文件,或通过程序导入数据流中的数据。
+
+## 基本原理
+
+下图展示了 Stream load 的主要流程,省略了一些导入细节。
+
+```
+ ^ +
+ | |
+ | | 1A. User submit load to FE
+ | |
+ | +--v-----------+
+ | | FE |
+5. Return result to user | +--+-----------+
+ | |
+ | | 2. Redirect to BE
+ | |
+ | +--v-----------+
+ +---+Coordinator BE| 1B. User submit load to BE
+ +-+-----+----+-+
+ | | |
+ +-----+ | +-----+
+ | | | 3. Distrbute data
+ | | |
+ +-v-+ +-v-+ +-v-+
+ |BE | |BE | |BE |
+ +---+ +---+ +---+
+```
+
+Stream load 中,Doris 会选定一个节点作为 Coordinator 节点。该节点负责接数据并分发数据到其他数据节点。
+
+用户通过 HTTP 协议提交导入命令。如果提交到 FE,则 FE 会通过 HTTP redirect 指令将请求转发给某一个 BE。用户也可以直接提交导入命令给某一指定 BE。
+
+导入的最终结果由 Coordinator BE 返回给用户。
+
+## 基本操作
+### 创建导入
+
+Stream load 通过 HTTP 协议提交和传输数据。这里通过 `curl` 命令展示如何提交导入。
+
+用户也可以通过其他 HTTP client 进行操作。
+
+```
+curl --location-trusted -u user:passwd [-H ""...] -T data.file -XPUT http://fe_host:http_port/api/{db}/{table}/_stream_load
+
+Header 中支持属性见下面的 ‘导入任务参数’ 说明
+格式为: -H "key1:value1"
+```
+
+示例:
+
+```
+curl --location-trusted -u root -T date -H "label:123" http://abc.com:8030/api/test/date/_stream_load
+```
+创建导入的详细语法帮助执行 ```HELP STREAM LOAD``` 查看, 下面主要介绍创建 Stream load 的部分参数意义。
+
+#### 签名参数
+
++ user/passwd
+
+ Stream load 由于创建导入的协议使用的是 HTTP 协议,通过 Basic access authentication 进行签名。Doris 系统会根据签名验证用户身份和导入权限。
+
+#### 导入任务参数
+
+Stream load 由于使用的是 HTTP 协议,所以所有导入任务有关的参数均设置在 Header 中。下面主要介绍了 Stream load 导入任务参数的部分参数意义。
+
++ label
+
+ 导入任务的标识。每个导入任务,都有一个在单 database 内部唯一的 label。label 是用户在导入命令中自定义的名称。通过这个 label,用户可以查看对应导入任务的执行情况。
+
+ label 的另一个作用,是防止用户重复导入相同的数据。**强烈推荐用户同一批次数据使用相同的 label。这样同一批次数据的重复请求只会被接受一次,保证了 At-Most-Once**
+
+ 当 label 对应的导入作业状态为 CANCELLED 时,该 label 可以再次被使用。
+
++ max\_filter\_ratio
+
+ 导入任务的最大容忍率,默认为0容忍,取值范围是0~1。当导入的错误率超过该值,则导入失败。
+
+ 如果用户希望忽略错误的行,可以通过设置这个参数大于 0,来保证导入可以成功。
+
+ 计算公式为:
+
+ ``` (dpp.abnorm.ALL / (dpp.abnorm.ALL + dpp.norm.ALL ) ) > max_filter_ratio ```
+
+ ```dpp.abnorm.ALL``` 表示数据质量不合格的行数。如类型不匹配,列数不匹配,长度不匹配等等。
+
+ ```dpp.norm.ALL``` 指的是导入过程中正确数据的条数。可以通过 ```SHOW LOAD``` 命令查询导入任务的正确数据量。
+
+ 原始文件的行数 = `dpp.abnorm.ALL + dpp.norm.ALL`
+
++ where
+
+ 导入任务指定的过滤条件。Stream load 支持对原始数据指定 where 语句进行过滤。被过滤的数据将不会被导入,也不会参与 filter ratio 的计算,但会被计入```num_rows_unselected```。
+
++ partition
+
+ 待导入表的 Partition 信息,如果待导入数据不属于指定的 Partition 则不会被导入。这些数据将计入 ```dpp.abnorm.ALL ```
+
++ columns
+
+ 待导入数据的函数变换配置,目前 Stream load 支持的函数变换方法包含列的顺序变化以及表达式变换,其中表达式变换的方法与查询语句的一致。
+
+ ```
+ 列顺序变换例子:原始数据有两列,目前表也有两列(c1,c2)但是原始文件的第一列对应的是目标表的c2列, 而原始文件的第二列对应的是目标表的c1列,则写法如下:
+ columns: c2,c1
+
+ 表达式变换例子:原始文件有两列,目标表也有两列(c1,c2)但是原始文件的两列均需要经过函数变换才能对应目标表的两列,则写法如下:
+ columns: tmp_c1, tmp_c2, c1 = year(tmp_c1), c2 = month(tmp_c2)
+ 其中 tmp_*是一个占位符,代表的是原始文件中的两个原始列。
+ ```
+
++ exec\_mem\_limit
+
+ 导入内存限制。默认为 2GB,单位为字节。
+
++ strict\_mode
+
+ Stream load 导入可以开启 strict mode 模式。开启方式为在 HEADER 中声明 ```strict_mode=true``` 。默认的 strict mode 为关闭。
+
+ strict mode 模式的意思是:对于导入过程中的列类型转换进行严格过滤。严格过滤的策略如下:
+
+ 1. 对于列类型转换来说,如果 strict mode 为true,则错误的数据将被 filter。这里的错误数据是指:原始数据并不为空值,在参与列类型转换后结果为空值的这一类数据。
+
+ 2. 对于导入的某列由函数变换生成时,strict mode 对其不产生影响。
+
+ 3. 对于导入的某列类型包含范围限制的,如果原始数据能正常通过类型转换,但无法通过范围限制的,strict mode 对其也不产生影响。例如:如果类型是 decimal(1,0), 原始数据为 10,则属于可以通过类型转换但不在列声明的范围内。这种数据 strict 对其不产生影响。
+
+#### strict mode 与 source data 的导入关系
+
+这里以列类型为 TinyInt 来举例
+
+>注:当表中的列允许导入空值时
+
+|source data | source data example | string to int | strict_mode | result|
+|------------|---------------------|-----------------|--------------------|---------|
+|空值 | \N | N/A | true or false | NULL|
+|not null | aaa or 2000 | NULL | true | invalid data(filtered)|
+|not null | aaa | NULL | false | NULL|
+|not null | 1 | 1 | true or false | correct data|
+
+这里以列类型为 Decimal(1,0) 举例
+
+>注:当表中的列允许导入空值时
+
+|source data | source data example | string to int | strict_mode | result|
+|------------|---------------------|-----------------|--------------------|--------|
+|空值 | \N | N/A | true or false | NULL|
+|not null | aaa | NULL | true | invalid data(filtered)|
+|not null | aaa | NULL | false | NULL|
+|not null | 1 or 10 | 1 | true or false | correct data|
+
+> 注意:10 虽然是一个超过范围的值,但是因为其类型符合 decimal的要求,所以 strict mode对其不产生影响。10 最后会在其他 ETL 处理流程中被过滤。但不会被 strict mode 过滤。
+
+
+### 返回结果
+
+由于 Stream load 是一种同步的导入方式,所以导入的结果会通过创建导入的返回值直接返回给用户。
+
+示例:
+
+```
+{
+ "TxnId": 1003,
+ "Label": "b6f3bc78-0d2c-45d9-9e4c-faa0a0149bee",
+ "Status": "Success",
+ "ExistingJobStatus": "FINISHED", // optional
+ "Message": "OK",
+ "NumberTotalRows": 1000000,
+ "NumberLoadedRows": 1000000,
+ "NumberFilteredRows": 1,
+ "NumberUnselectedRows": 0,
+ "LoadBytes": 40888898,
+ "LoadTimeMs": 2144,
+ "ErrorURL": "http://192.168.1.1:8042/api/_load_error_log?file=__shard_0/error_log_insert_stmt_db18266d4d9b4ee5-abb00ddd64bdf005_db18266d4d9b4ee5_abb00ddd64bdf005"
+}
+```
+
+下面主要解释了 Stream load 导入结果参数:
+
++ TxnId:导入的事务ID。用户可不感知。
+
++ Label:导入 Label。由用户指定或系统自动生成。
+
++ Status:导入完成状态。
+
+ "Success":表示导入成功。
+
+ "Publish Timeout":该状态也表示导入已经完成,只是数据可能会延迟可见,无需重试。
+
+ "Label Already Exists":Label 重复,需更换 Label。
+
+ "Fail":导入失败。
+
++ ExistingJobStatus:已存在的 Label 对应的导入作业的状态。
+
+ 这个字段只有在当 Status 为 "Label Already Exists" 是才会显示。用户可以通过这个状态,知晓已存在 Label 对应的导入作业的状态。"RUNNING" 表示作业还在执行,"FINISHED" 表示作业成功。
+
++ Message:导入错误信息。
+
++ NumberTotalRows:导入总处理的行数。
+
++ NumberLoadedRows:成功导入的行数。
+
++ NumberFilteredRows:数据质量不合格的行数。
+
++ NumberUnselectedRows:被 where 条件过滤的行数。
+
++ LoadBytes:导入的字节数。
+
++ LoadTimeMs:导入完成时间。单位毫秒。
+
++ ErrorURL:如果有数据质量问题,通过访问这个 URL 查看具体错误行。
+
+> 注意:由于 Stream load 是同步的导入方式,所以并不会在 Doris 系统中记录导入信息,用户无法异步的通过查看导入命令看到 Stream load。使用时需监听创建导入请求的返回值获取导入结果。
+
+### 取消导入
+
+用户无法手动取消 Stream load,Stream load 在超时或者导入错误后会被系统自动取消。
+
+## 相关系统配置
+
+### FE 配置
+
++ stream\_load\_default\_timeout\_second
+
+ 导入任务的超时时间(以秒为单位),导入任务在设定的 timeout 时间内未完成则会被系统取消,变成 CANCELLED。
+
+ 默认的 timeout 时间为 600 秒。如果导入的源文件无法在规定时间内完成导入,用户可以在 stream load 请求中设置单独的超时时间。
+
+ 或者调整 FE 的参数```stream_load_default_timeout_second``` 来设置全局的默认超时时间。
+
+### BE 配置
+
++ streaming\_load\_max\_mb
+
+ Stream load 的最大导入大小,默认为 10G,单位是 MB。如果用户的原始文件超过这个值,则需要调整 BE 的参数 ```streaming_load_max_mb```。
+
+## 最佳实践
+
+### 应用场景
+
+使用 Stream load 的最合适场景就是原始文件在内存中,或者在磁盘中。其次,由于 Stream load 是一种同步的导入方式,所以用户如果希望用同步方式获取导入结果,也可以使用这种导入。
+
+### 数据量
+
+由于 Stream load 的原理是由 BE 发起的导入并分发数据,建议的导入数据量在 1G 到 10G 之间。由于默认的最大 Stream load 导入数据量为 10G,所以如果要导入超过 10G 的文件需要修改 BE 的配置 ```streaming_load_max_mb```
+
+```
+比如:待导入文件大小为15G
+修改 BE 配置 streaming_load_max_mb 为 16000 即可。
+```
+
+Stream load 的默认超时为 300秒,按照 Doris 目前最大的导入限速来看,约超过 3G 的文件就需要修改导入任务默认超时时间了。
+
+```
+导入任务超时时间 = 导入数据量 / 10M/s (具体的平均导入速度需要用户根据自己的集群情况计算)
+例如:导入一个 10G 的文件
+timeout = 1000s 等于 10G / 10M/s
+```
+
+### 完整例子
+数据情况: 数据在发送导入请求端的本地磁盘路径 /home/store_sales 中,导入的数据量约为 15G,希望导入到数据库 bj_sales 的表 store_sales 中。
+
+集群情况:Stream load 的并发数不受集群大小影响。
+
++ step1: 导入文件大小是否超过默认的最大导入大小10G
+
+ ```
+ 修改 BE conf
+ streaming_load_max_mb = 16000
+ ```
++ step2: 计算大概的导入时间是否超过默认 timeout 值
+
+ ```
+ 导入时间 ≈ 15000 / 10 = 1500s
+ 超过了默认的 timeout 时间,需要修改 FE 的配置
+ stream_load_default_timeout_second = 1500
+ ```
+
++ step3:创建导入任务
+
+ ```
+ curl --location-trusted -u user:password -T /home/store_sales -H "label:abc" http://abc.com:8000/api/bj_sales/store_sales/_stream_load
+ ```
+
+## 常见问题
+
+* Label Already Exists
+
+ Stream load 的 Label 重复排查步骤如下:
+
+ 1. 是否和其他导入方式已经存在的导入 Label 冲突:
+
+ 由于 Doris 系统中导入的 Label 不区分导入方式,所以存在其他导入方式使用了相同 Label 的问题。
+
+ 通过 ```SHOW LOAD WHERE LABEL = “xxx”```,其中 xxx 为重复的 Label 字符串,查看是否已经存在一个 FINISHED 导入的 Label 和用户申请创建的 Label 相同。
+
+ 2. 是否 Stream load 同一个作业被重复提交了
+
+ 由于 Stream load 是 HTTP 协议提交创建导入任务,一般各个语言的 HTTP Client 均会自带请求重试逻辑。Doris 系统在接受到第一个请求后,已经开始操作 Stream load,但是由于没有及时返回给 Client 端结果, Client 端会发生再次重试创建请求的情况。这时候 Doris 系统由于已经在操作第一个请求,所以第二个请求已经就会被报 Label Already Exists 的情况。
+
+ 排查上述可能的方法:使用 Label 搜索 FE Master 的日志,看是否存在同一个 Label 出现了两次 ```redirect load action to destination= ``` 的情况。如果有就说明,请求被 Client 端重复提交了。
+
+ 建议用户根据当前请求的数据量,计算出大致导入的时间,并根据导入超时时间改大 Client 端的请求超时时间,避免请求被 Client 端多次提交。
+
+
+
diff --git a/docs/documentation/cn/administrator-guide/operation/disk-capacity.md b/docs/zh-CN/administrator-guide/operation/disk-capacity.md
similarity index 98%
rename from docs/documentation/cn/administrator-guide/operation/disk-capacity.md
rename to docs/zh-CN/administrator-guide/operation/disk-capacity.md
index 8c9746fd973639..e3e7f5ba508000 100644
--- a/docs/documentation/cn/administrator-guide/operation/disk-capacity.md
+++ b/docs/zh-CN/administrator-guide/operation/disk-capacity.md
@@ -1,3 +1,10 @@
+---
+{
+ "title": "磁盘空间管理",
+ "language": "zh-CN"
+}
+---
+
+
+# 元数据运维
+
+本文档主要介绍在实际生产环境中,如何对 Doris 的元数据进行管理。包括 FE 节点建议的部署方式、一些常用的操作方法、以及常见错误的解决方法。
+
+在阅读本文当前,请先阅读 [Doris 元数据设计文档](../../internal/metadata-design.md) 了解 Doris 元数据的工作原理。
+
+## 重要提示
+
+* 当前元数据的设计是无法向后兼容的。即如果新版本有新增的元数据结构变动(可以查看 FE 代码中的 `FeMetaVersion.java` 文件中是否有新增的 VERSION),那么在升级到新版本后,通常是无法再回滚到旧版本的。所以,在升级 FE 之前,请务必按照 [升级文档](../../installing/upgrade.md) 中的操作,测试元数据兼容性。
+
+## 元数据目录结构
+
+我们假设在 fe.conf 中指定的 `meta_dir` 的路径为 `/path/to/palo-meta`。那么一个正常运行中的 Doris 集群,元数据的目录结构应该如下:
+
+```
+/path/to/palo-meta/
+ |-- bdb/
+ | |-- 00000000.jdb
+ | |-- je.config.csv
+ | |-- je.info.0
+ | |-- je.info.0.lck
+ | |-- je.lck
+ | `-- je.stat.csv
+ `-- image/
+ |-- ROLE
+ |-- VERSION
+ `-- image.xxxx
+```
+
+1. bdb 目录
+
+ 我们将 [bdbje](https://www.oracle.com/technetwork/database/berkeleydb/overview/index-093405.html) 作为一个分布式的 kv 系统,存放元数据的 journal。这个 bdb 目录相当于 bdbje 的 “数据目录”。
+
+ 其中 `.jdb` 后缀的是 bdbje 的数据文件。这些数据文件会随着元数据 journal 的不断增多而越来越多。当 Doris 定期做完 image 后,旧的日志就会被删除。所以正常情况下,这些数据文件的总大小从几 MB 到几 GB 不等(取决于使用 Doris 的方式,如导入频率等)。当数据文件的总大小大于 10GB,则可能需要怀疑是否是因为 image 没有成功,或者分发 image 失败导致的历史 journal 一直无法删除。
+
+ `je.info.0` 是 bdbje 的运行日志。这个日志中的时间是 UTC+0 时区的。我们可能在后面的某个版本中修复这个问题。通过这个日志,也可以查看一些 bdbje 的运行情况。
+
+2. image 目录
+
+ image 目录用于存放 Doris 定期生成的元数据镜像文件。通常情况下,你会看到有一个 `image.xxxxx` 的镜像文件。其中 `xxxxx` 是一个数字。这个数字表示该镜像包含 `xxxxx` 号之前的所有元数据 journal。而这个文件的生成时间(通过 `ls -al` 查看即可)通常就是镜像的生成时间。
+
+ 你也可能会看到一个 `image.ckpt` 文件。这是一个正在生成的元数据镜像。通过 `du -sh` 命令应该可以看到这个文件大小在不断变大,说明镜像内容正在写入这个文件。当镜像写完后,会自动重名为一个新的 `image.xxxxx` 并替换旧的 image 文件。
+
+ 只有角色为 Master 的 FE 才会主动定期生成 image 文件。每次生成完后,都会推送给其他非 Master 角色的 FE。当确认其他所有 FE 都收到这个 image 后,Master FE 会删除 bdbje 中旧的元数据 journal。所以,如果 image 生成失败,或者 image 推送给其他 FE 失败时,都会导致 bdbje 中的数据不断累积。
+
+ `ROLE` 文件记录了 FE 的类型(FOLLOWER 或 OBSERVER),是一个文本文件。
+
+ `VERSION` 文件记录了这个 Doris 集群的 cluster id,以及用于各个节点之间访问认证的 token,也是一个文本文件。
+
+ `ROLE` 文件和 `VERSION` 文件只可能同时存在,或同时不存在(如第一次启动时)。
+
+## 基本操作
+
+### 启动单节点 FE
+
+单节点 FE 是最基本的一种部署方式。一个完整的 Doris 集群,至少需要一个 FE 节点。当只有一个 FE 节点时,这个节点的类型为 Follower,角色为 Master。
+
+1. 第一次启动
+
+ 1. 假设在 fe.conf 中指定的 `meta_dir` 的路径为 `/path/to/palo-meta`。
+ 2. 确保 `/path/to/palo-meta` 已存在,权限正确,且目录为空。
+ 3. 直接通过 `sh bin/start_fe.sh` 即可启动。
+ 4. 启动后,你应该可以在 fe.log 中看到如下日志:
+
+ * Palo FE starting...
+ * image does not exist: /path/to/palo-meta/image/image.0
+ * transfer from INIT to UNKNOWN
+ * transfer from UNKNOWN to MASTER
+ * the very first time to open bdb, dbname is 1
+ * start fencing, epoch number is 1
+ * finish replay in xxx msec
+ * QE service start
+ * thrift server started
+
+ 以上日志不一定严格按照这个顺序,但基本类似。
+
+ 5. 单节点 FE 的第一次启动通常不会遇到问题。如果你没有看到以上日志,一般来说是没有仔细按照文档步骤操作,请仔细阅读相关 wiki。
+
+2. 重启
+
+ 1. 直接使用 `sh bin/start_fe.sh` 可以重新启动已经停止的 FE 节点。
+ 2. 重启后,你应该可以在 fe.log 中看到如下日志:
+
+ * Palo FE starting...
+ * finished to get cluster id: xxxx, role: FOLLOWER and node name: xxxx
+ * 如果重启前还没有 image 产生,则会看到:
+ * image does not exist: /path/to/palo-meta/image/image.0
+
+ * 如果重启前有 image 产生,则会看到:
+ * start load image from /path/to/palo-meta/image/image.xxx. is ckpt: false
+ * finished load image in xxx ms
+
+ * transfer from INIT to UNKNOWN
+ * replayed journal id is xxxx, replay to journal id is yyyy
+ * transfer from UNKNOWN to MASTER
+ * finish replay in xxx msec
+ * master finish replay journal, can write now.
+ * begin to generate new image: image.xxxx
+ * start save image to /path/to/palo-meta/image/image.ckpt. is ckpt: true
+ * finished save image /path/to/palo-meta/image/image.ckpt in xxx ms. checksum is xxxx
+ * push image.xxx to other nodes. totally xx nodes, push successed xx nodes
+ * QE service start
+ * thrift server started
+
+ 以上日志不一定严格按照这个顺序,但基本类似。
+
+3. 常见问题
+
+ 对于单节点 FE 的部署,启停通常不会遇到什么问题。如果有问题,请先参照相关 wiki,仔细核对你的操作步骤。
+
+### 添加 FE
+
+添加 FE 流程在 [部署和升级文档](https://github.com/apache/incubator-doris/wiki/Doris-Deploy-%26-Upgrade) 有详细介绍,不再赘述。这里主要说明一些注意事项,以及常见问题。
+
+1. 注意事项
+
+ * 在添加新的 FE 之前,一定先确保当前的 Master FE 运行正常(连接是否正常,JVM 是否正常,image 生成是否正常,bdbje 数据目录是否过大等等)
+ * 第一次启动新的 FE,一定确保添加了 `-helper` 参数指向 Master FE。再次启动时可不用添加 `-helper`。(如果指定了 `-helper`,FE 会直接询问 helper 节点自己的角色,如果没有指定,FE会尝试从 `palo-meta/image/` 目录下的 `ROLE` 和 `VERSION` 文件中获取信息)。
+ * 第一次启动新的 FE,一定确保这个 FE 的 `meta_dir` 已经创建、权限正确且为空。
+ * 启动新的 FE,和执行 `ALTER SYSTEM ADD FOLLOWER/OBSERVER` 语句在元数据添加 FE,这两个操作的顺序没有先后要求。如果先启动了新的 FE,而没有执行语句,则新的 FE 日志中会一直滚动 `current node is not added to the group. please add it first.` 字样。当执行语句后,则会进入正常流程。
+ * 请确保前一个 FE 添加成功后,再添加下一个 FE。
+ * 建议直接连接到 MASTER FE 执行 `ALTER SYSTEM ADD FOLLOWER/OBSERVER` 语句。
+
+2. 常见问题
+
+ 1. this node is DETACHED
+
+ 当第一次启动一个待添加的 FE 时,如果 Master FE 上的 palo-meta/bdb 中的数据很大,则可能在待添加的 FE 日志中看到 `this node is DETACHED.` 字样。这时,bdbje 正在复制数据,你可以看到待添加的 FE 的 `bdb/` 目录正在变大。这个过程通常会在数分钟不等(取决于 bdbje 中的数据量)。之后,fe.log 中可能会有一些 bdbje 相关的错误堆栈信息。如果最终日志中显示 `QE service start` 和 `thrift server started`,则通常表示启动成功。可以通过 mysql-client 连接这个 FE 尝试操作。如果没有出现这些字样,则可能是 bdbje 复制日志超时等问题。这时,直接再次重启这个 FE,通常即可解决问题。
+
+ 2. 各种原因导致添加失败
+
+ * 如果添加的是 OBSERVER,因为 OBSERVER 类型的 FE 不参与元数据的多数写,理论上可以随意启停。因此,对于添加 OBSERVER 失败的情况。可以直接杀死 OBSERVER FE 的进程,清空 OBSERVER 的元数据目录后,重新进行一遍添加流程。
+
+ * 如果添加的是 FOLLOWER,因为 FOLLOWER 是参与元数据多数写的。所以有可能FOLLOWER 已经加入 bdbje 选举组内。如果这时只有两个 FOLLOWER 节点(包括 MASTER),那么停掉一个 FE,可能导致另一个 FE 也因无法进行多数写而退出。此时,我们应该先通过 `ALTER SYSTEM DROP FOLLOWER` 命令,从元数据中删除新添加的 FOLLOWER 节点,然后再杀死 FOLLOWER 进程,清空元数据,重新进行一遍添加流程。
+
+
+### 删除 FE
+
+通过 `ALTER SYSTEM DROP FOLLOWER/OBSERVER` 命令即可删除对应类型的 FE。以下有几点注意事项:
+
+* 对于 OBSERVER 类型的 FE,直接 DROP 即可,无风险。
+
+* 对于 FOLLOWER 类型的 FE。首先,应保证在有奇数个 FOLLOWER 的情况下(3个或以上),开始删除操作。
+
+ 1. 如果删除非 MASTER 角色的 FE,建议连接到 MASTER FE,执行 DROP 命令,再杀死进程即可。
+ 2. 如果要删除 MASTER FE,先确认有奇数个 FOLLOWER FE 并且运行正常。然后先杀死 MASTER FE 的进程。这时会有某一个 FE 被选举为 MASTER。在确认剩下的 FE 运行正常后,连接到新的 MASTER FE,执行 DROP 命令删除之前老的 MASTER FE 即可。
+
+## 高级操作
+
+### 故障恢复
+
+FE 有可能因为某些原因出现无法启动 bdbje、FE 之间无法同步等问题。现象包括无法进行元数据写操作、没有 MASTER 等等。这时,我们需要手动操作来恢复 FE。手动恢复 FE 的大致原理,是先通过当前 `meta_dir` 中的元数据,启动一个新的 MASTER,然后再逐台添加其他 FE。请严格按照如下步骤操作:
+
+1. 首先,停止所有 FE 进程,同时停止一切业务访问。保证在元数据恢复期间,不会因为外部访问导致其他不可预期的问题。
+
+2. 确认哪个 FE 节点的元数据是最新:
+
+ * 首先,**务必先备份所有 FE 的 `meta_dir` 目录。**
+ * 通常情况下,Master FE 的元数据是最新的。可以查看 `meta_dir/image` 目录下,image.xxxx 文件的后缀,数字越大,则表示元数据越新。
+ * 通常,通过比较所有 FOLLOWER FE 的 image 文件,找出最新的元数据即可。
+ * 之后,我们要使用这个拥有最新元数据的 FE 节点,进行恢复。
+ * 如果使用 OBSERVER 节点的元数据进行恢复会比较麻烦,建议尽量选择 FOLLOWER 节点。
+
+3. 以下操作都在由第2步中选择出来的 FE 节点上进行。
+
+ 1. 如果该节点是一个 OBSERVER,先将 `meta_dir/image/ROLE` 文件中的 `role=OBSERVER` 改为 `role=FOLLOWER`。(从 OBSERVER 节点恢复会比较麻烦,先按这里的步骤操作,后面会有单独说明)
+ 2. 在 fe.conf 中添加配置:`metadata_failure_recovery=true`。
+ 3. 执行 `sh bin/start_fe.sh` 启动这个 FE。
+ 4. 如果正常,这个 FE 会以 MASTER 的角色启动,类似于前面 `启动单节点 FE` 一节中的描述。在 fe.log 应该会看到 `transfer from XXXX to MASTER` 等字样。
+ 5. 启动完成后,先连接到这个 FE,执行一些查询导入,检查是否能够正常访问。如果不正常,有可能是操作有误,建议仔细阅读以上步骤,用之前备份的元数据再试一次。如果还是不行,问题可能就比较严重了。
+ 6. 如果成功,通过 `show frontends;` 命令,应该可以看到之前所添加的所有 FE,并且当前 FE 是 master。
+ 7. 将 fe.conf 中的 `metadata_failure_recovery=true` 配置项删除,或者设置为 `false`,然后重启这个 FE(**重要**)。
+
+
+ > 如果你是从一个 OBSERVER 节点的元数据进行恢复的,那么完成如上步骤后,通过 `show frontends;` 语句你会发现,当前这个 FE 的角色为 OBSERVER,但是 `IsMaster` 显示为 `true`。这是因为,这里看到的 “OBSERVER” 是记录在 Doris 的元数据中的,而是否是 master,是记录在 bdbje 的元数据中的。因为我们是从一个 OBSERVER 节点恢复的,所以这里出现了不一致。请按如下步骤修复这个问题(这个问题我们会在之后的某个版本修复):
+
+ > 1. 先把除了这个 “OBSERVER” 以外的所有 FE 节点 DROP 掉。
+ > 2. 通过 `ADD FOLLOWER` 命令,添加一个新的 FOLLOWER FE,假设在 hostA 上。
+ > 3. 在 hostA 上启动一个全新的 FE,通过 `-helper` 的方式加入集群。
+ > 4. 启动成功后,通过 `show frontends;` 语句,你应该能看到两个 FE,一个是之前的 OBSERVER,一个是新添加的 FOLLOWER,并且 OBSERVER 是 master。
+ > 5. 确认这个新的 FOLLOWER 是可以正常工作之后,用这个新的 FOLLOWER 的元数据,重新执行一遍故障恢复操作。
+ > 6. 以上这些步骤的目的,其实就是人为的制造出一个 FOLLOWER 节点的元数据,然后用这个元数据,重新开始故障恢复。这样就避免了从 OBSERVER 恢复元数据所遇到的不一致的问题。
+
+ > `metadata_failure_recovery=true` 的含义是,清空 "bdbje" 的元数据。这样 bdbje 就不会再联系之前的其他 FE 了,而作为一个独立的 FE 启动。这个参数只有在恢复启动时才需要设置为 true。恢复完成后,一定要设置为 false,否则一旦重启,bdbje 的元数据又会被清空,导致其他 FE 无法正常工作。
+
+4. 第3步执行成功后,我们再通过 `ALTER SYSTEM DROP FOLLOWER/OBSERVER` 命令,将之前的其他的 FE 从元数据删除后,按加入新 FE 的方式,重新把这些 FE 添加一遍。
+
+5. 如果以上操作正常,则恢复完毕。
+
+### FE 类型变更
+
+如果你需要将当前已有的 FOLLOWER/OBSERVER 类型的 FE,变更为 OBSERVER/FOLLOWER 类型,请先按照前面所述的方式删除 FE,再添加对应类型的 FE 即可
+
+### FE 迁移
+
+如果你需要将一个 FE 从当前节点迁移到另一个节点,分以下几种情况。
+
+1. 非 MASTER 节点的 FOLLOWER,或者 OBSERVER 迁移
+
+ 直接添加新的 FOLLOWER/OBSERVER 成功后,删除旧的 FOLLOWER/OBSERVER 即可。
+
+2. 单节点 MASTER 迁移
+
+ 当只有一个 FE 时,参考 `故障恢复` 一节。将 FE 的 palo-meta 目录拷贝到新节点上,按照 `故障恢复` 一节中,步骤3的方式启动新的 MASTER
+
+3. 一组 FOLLOWER 从一组节点迁移到另一组新的节点
+
+ 在新的节点上部署 FE,通过添加 FOLLOWER 的方式先加入新节点。再逐台 DROP 掉旧节点即可。在逐台 DROP 的过程中,MASTER 会自动选择在新的 FOLLOWER 节点上。
+
+### 更换 FE 端口
+
+FE 目前有以下几个端口
+
+* edit_log_port:bdbje 的通信端口
+* http_port:http 端口,也用于推送 image
+* rpc_port:FE 的 thrift server port
+* query_port:Mysql 连接端口
+
+1. edit_log_port
+
+ 如果需要更换这个端口,则需要参照 `故障恢复` 一节中的操作,进行恢复。因为该端口已经被持久化到 bdbje 自己的元数据中(同时也记录在 Doris 自己的元数据中),需要通过设置 `metadata_failure_recovery=true` 来清空 bdbje 的元数据。
+
+2. http_port
+
+ 所有 FE 的 http_port 必须保持一致。所以如果要修改这个端口,则所有 FE 都需要修改并重启。修改这个端口,在多 FOLLOWER 部署的情况下会比较复杂(涉及到鸡生蛋蛋生鸡的问题...),所以不建议有这种操作。如果必须,直接按照 `故障恢复` 一节中的操作吧。
+
+3. rpc_port
+
+ 修改配置后,直接重启 FE 即可。Master FE 会通过心跳将新的端口告知 BE。只有 Master FE 的这个端口会被使用。但仍然建议所有 FE 的端口保持一致。
+
+4. query_port
+
+ 修改配置后,直接重启 FE 即可。这个只影响到 mysql 的连接目标。
+
+
+### 从 FE 内存中恢复元数据
+
+在某些极端情况下,磁盘上 image 文件可能会损坏,但是内存中的元数据是完好的,此时我们可以先从内存中 dump 出元数据,再替换掉磁盘上的 image 文件,来恢复元数据,整个**不停查询服务**的操作步骤如下:
+1. 集群停止所有 Load,Create,Alter 操作
+2. 执行以下命令,从 Master FE 内存中 dump 出元数据:(下面称为 image_mem)
+```
+curl -u $root_user:$password http://$master_hostname:8030/dump
+```
+3. 用 image_mem 文件替换掉 OBSERVER FE 节点上`meta_dir/image`目录下的 image 文件,重启 OBSERVER FE 节点,
+验证 image_mem 文件的完整性和正确性(可以在 FE Web 页面查看 DB 和 Table 的元数据是否正常,查看fe.log 是否有异常,是否在正常 replayed journal)
+4. 依次用 image_mem 文件替换掉 FOLLOWER FE 节点上`meta_dir/image`目录下的 image 文件,重启 FOLLOWER FE 节点,
+确认元数据和查询服务都正常
+5. 用 image_mem 文件替换掉 Master FE 节点上`meta_dir/image`目录下的 image 文件,重启 Master FE 节点,
+确认 FE Master 切换正常, Master FE 节点可以通过 checkpoint 正常生成新的 image 文件
+6. 集群恢复所有 Load,Create,Alter 操作
+
+**注意:如果 Image 文件很大,整个操作过程耗时可能会很长,所以在此期间,要确保 Master FE 不会通过 checkpoint 生成新的 image 文件。
+当观察到 Master FE 节点上 `meta_dir/image`目录下的 `image.ckpt` 文件快和 `image.xxx` 文件一样大时,可以直接删除掉`image.ckpt` 文件。**
+
+## 最佳实践
+
+FE 的部署推荐,在 [安装与部署文档](../../installing/install-deploy.md) 中有介绍,这里再做一些补充。
+
+* **如果你并不十分了解 FE 元数据的运行逻辑,或者没有足够 FE 元数据的运维经验,我们强烈建议在实际使用中,只部署一个 FOLLOWER 类型的 FE 作为 MASTER,其余 FE 都是 OBSERVER,这样可以减少很多复杂的运维问题!** 不用过于担心 MASTER 单点故障导致无法进行元数据写操作。首先,如果你配置合理,FE 作为 java 进程很难挂掉。其次,如果 MASTER 磁盘损坏(概率非常低),我们也可以用 OBSERVER 上的元数据,通过 `故障恢复` 的方式手动恢复。
+
+* FE 进程的 JVM 一定要保证足够的内存。我们**强烈建议** FE 的 JVM 内存至少在 10GB 以上,推荐 32GB 至 64GB。并且部署监控来监控 JVM 的内存使用情况。因为如果FE出现OOM,可能导致元数据写入失败,造成一些**无法恢复**的故障!
+
+* FE 所在节点要有足够的磁盘空间,以防止元数据过大导致磁盘空间不足。同时 FE 日志也会占用十几G 的磁盘空间。
+
+## 其他常见问题
+
+1. fe.log 中一直滚动 `meta out of date. current time: xxx, synchronized time: xxx, has log: xxx, fe type: xxx`
+
+ 这个通常是因为 FE 无法选举出 Master。比如配置了 3 个 FOLLOWER,但是只启动了一个 FOLLOWER,则这个 FOLLOWER 会出现这个问题。通常,只要把剩余的 FOLLOWER 启动起来就可以了。如果启动起来后,仍然没有解决问题,那么可能需要按照 `故障恢复` 一节中的方式,手动进行恢复。
+
+2. `Clock delta: xxxx ms. between Feeder: xxxx and this Replica exceeds max permissible delta: xxxx ms.`
+
+ bdbje 要求各个节点之间的时钟误差不能超过一定阈值。如果超过,节点会异常退出。我们默认设置的阈值为 5000 ms,由 FE 的参数 `max_bdbje_clock_delta_ms` 控制,可以酌情修改。但我们建议使用 ntp 等时钟同步方式保证 Doris 集群各主机的时钟同步。
+
+
+3. `image/` 目录下的镜像文件很久没有更新
+
+ Master FE 会默认每 50000 条元数据 journal,生成一个镜像文件。在一个频繁使用的集群中,通常每隔半天到几天的时间,就会生成一个新的 image 文件。如果你发现 image 文件已经很久没有更新了(比如超过一个星期),则可以顺序的按照如下方法,查看具体原因:
+
+ 1. 在 Master FE 的 fe.log 中搜索 `memory is not enough to do checkpoint. Committed memroy xxxx Bytes, used memory xxxx Bytes.` 字样。如果找到,则说明当前 FE 的 JVM 内存不足以用于生成镜像(通常我们需要预留一半的 FE 内存用于 image 的生成)。那么需要增加 JVM 的内存并重启 FE 后,再观察。每次 Master FE 重启后,都会直接生成一个新的 image。也可用这种重启方式,主动地生成新的 image。注意,如果是多 FOLLOWER 部署,那么当你重启当前 Master FE 后,另一个 FOLLOWER FE 会变成 MASTER,则后续的 image 生成会由新的 Master 负责。因此,你可能需要修改所有 FOLLOWER FE 的 JVM 内存配置。
+
+ 2. 在 Master FE 的 fe.log 中搜索 `begin to generate new image: image.xxxx`。如果找到,则说明开始生成 image 了。检查这个线程的后续日志,如果出现 `checkpoint finished save image.xxxx`,则说明 image 写入成功。如果出现 `Exception when generate new image file`,则生成失败,需要查看具体的错误信息。
+
+
+4. `bdb/` 目录的大小非常大,达到几个G或更多
+
+ 如果在排除无法生成新的 image 的错误后,bdb 目录在一段时间内依然很大。则可能是因为 Master FE 推送 image 不成功。可以在 Master FE 的 fe.log 中搜索 `push image.xxxx to other nodes. totally xx nodes, push successed yy nodes`。如果 yy 比 xx 小,则说明有的 FE 没有被推送成功。可以在 fe.log 中查看到具体的错误 `Exception when pushing image file. url = xxx`。
+
+ 同时,你也可以在 FE 的配置文件中添加配置:`edit_log_roll_num=xxxx`。该参数设定了每多少条元数据 journal,做一次 image。默认是 50000。可以适当改小这个数字,使得 image 更加频繁,从而加速删除旧的 journal。
+
+5. FOLLOWER FE 接连挂掉
+
+ 因为 Doris 的元数据采用多数写策略,即一条元数据 journal 必须至少写入多数个 FOLLOWER FE 后(比如 3 个 FOLLOWER,必须写成功 2 个),才算成功。而如果写入失败,FE 进程会主动退出。那么假设有 A、B、C 三个 FOLLOWER,C 先挂掉,然后 B 再挂掉,那么 A 也会跟着挂掉。所以如 `最佳实践` 一节中所述,如果你没有丰富的元数据运维经验,不建议部署多 FOLLOWER。
+
+6. fe.log 中出现 `get exception when try to close previously opened bdb database. ignore it`
+
+ 如果后面有 `ignore it` 字样,通常无需处理。如果你有兴趣,可以在 `BDBEnvironment.java` 搜索这个错误,查看相关注释说明。
+
+7. 从 `show frontends;` 看,某个 FE 的 `Join` 列为 `true`,但是实际该 FE 不正常
+
+ 通过 `show frontends;` 查看到的 `Join` 信息。该列如果为 `true`,仅表示这个 FE **曾经加入过** 集群。并不能表示当前仍然正常的存在于集群中。如果为 `false`,则表示这个 FE **从未加入过** 集群。
+
+8. 关于 FE 的配置 `master_sync_policy`, `replica_sync_policy` 和 `txn_rollback_limit`
+
+ `master_sync_policy` 用于指定当 Leader FE 写元数据日志时,是否调用 fsync(), `replica_sync_policy` 用于指定当 FE HA 部署时,其他 Follower FE 在同步元数据时,是否调用 fsync()。在早期的 Doris 版本中,这两个参数默认是 `WRITE_NO_SYNC`,即都不调用 fsync()。在最新版本的 Doris 中,默认已修改为 `SYNC`,即都调用 fsync()。调用 fsync() 会显著降低元数据写盘的效率。在某些环境下,IOPS 可能降至几百,延迟增加到2-3ms(但对于 Doris 元数据操作依然够用)。因此我们建议以下配置:
+
+ 1. 对于单 Follower FE 部署,`master_sync_policy` 设置为 `SYNC`,防止 FE 系统宕机导致元数据丢失。
+ 2. 对于多 Follower FE 部署,可以将 `master_sync_policy` 和 `replica_sync_policy` 设为 `WRITE_NO_SYNC`,因为我们认为多个系统同时宕机的概率非常低。
+
+ 如果在单 Follower FE 部署中,`master_sync_policy` 设置为 `WRITE_NO_SYNC`,则可能出现 FE 系统宕机导致元数据丢失。这时如果有其他 Observer FE 尝试重启时,可能会报错:
+
+ ```
+ Node xxx must rollback xx total commits(numPassedDurableCommits of which were durable) to the earliest point indicated by transaction xxxx in order to rejoin the replication group, but the transaction rollback limit of xxx prohibits this.
+ ```
+
+ 意思有部分已经持久化的事务需要回滚,但条数超过上限。这里我们的默认上限是 100,可以通过设置 `txn_rollback_limit` 改变。该操作仅用于尝试正常启动 FE,但已丢失的元数据无法恢复。
diff --git a/docs/zh-CN/administrator-guide/operation/monitor-alert.md b/docs/zh-CN/administrator-guide/operation/monitor-alert.md
new file mode 100644
index 00000000000000..c22225cc7ae081
--- /dev/null
+++ b/docs/zh-CN/administrator-guide/operation/monitor-alert.md
@@ -0,0 +1,309 @@
+---
+{
+ "title": "监控和报警",
+ "language": "zh-CN"
+}
+---
+
+
+
+# 监控和报警
+
+本文档主要介绍 Doris 的监控项及如何采集、展示监控项。以及如何配置报警(TODO)
+
+[Dashborad 模板点击下载](https://grafana.com/dashboards/9734/revisions)
+
+> 注:0.9.0(不含)之前的版本请使用 revision 1。0.9.x 版本请使用 revision 2。0.10.x 版本请使用 revision 3。
+
+Dashboard 模板会不定期更新。更新模板的方式见最后一小节。
+
+欢迎提供更优的 dashboard。
+
+## 组件
+
+Doris 使用 [Prometheus](https://prometheus.io/) 和 [Grafana](https://grafana.com/) 进项监控项的采集和展示。
+
+
+
+1. Prometheus
+
+ Prometheus 是一款开源的系统监控和报警套件。它可以通过 Pull 或 Push 采集被监控系统的监控项,存入自身的时序数据库中。并且通过丰富的多维数据查询语言,满足用户的不同数据展示需求。
+
+2. Grafana
+
+ Grafana 是一款开源的数据分析和展示平台。支持包括 Prometheus 在内的多个主流时序数据库源。通过对应的数据库查询语句,从数据源中获取展现数据。通过灵活可配置的 Dashboard,快速的将这些数据以图表的形式展示给用户。
+
+> 注: 本文档仅提供一种使用 Prometheus 和 Grafana 进行 Doris 监控数据采集和展示的方式。原则上不开发、维护这些组件。更多关于这些组件的详细介绍,请移步对应官方文档进行查阅。
+
+## 监控数据
+
+Doris 的监控数据通过 Frontend 和 Backend 的 http 接口向外暴露。监控数据以 Key-Value 的文本形式对外展现。每个 Key 还可能有不同的 Label 加以区分。当用户搭建好 Doris 后,可以在浏览器,通过以下接口访问到节点的监控数据:
+
+* Frontend: `fe_host:fe_http_port/metrics`
+* Backend: `be_host:be_web_server_port/metrics`
+* Broker: 暂不提供
+
+用户将看到如下监控项结果(示例为 FE 部分监控项):
+
+ ```
+ # HELP jvm_heap_size_bytes jvm heap stat
+ # TYPE jvm_heap_size_bytes gauge
+ jvm_heap_size_bytes{type="max"} 41661235200
+ jvm_heap_size_bytes{type="committed"} 19785285632
+ jvm_heap_size_bytes{type="used"} 10113221064
+ # HELP jvm_non_heap_size_bytes jvm non heap stat
+ # TYPE jvm_non_heap_size_bytes gauge
+ jvm_non_heap_size_bytes{type="committed"} 105295872
+ jvm_non_heap_size_bytes{type="used"} 103184784
+ # HELP jvm_young_size_bytes jvm young mem pool stat
+ # TYPE jvm_young_size_bytes gauge
+ jvm_young_size_bytes{type="used"} 6505306808
+ jvm_young_size_bytes{type="peak_used"} 10308026368
+ jvm_young_size_bytes{type="max"} 10308026368
+ # HELP jvm_old_size_bytes jvm old mem pool stat
+ # TYPE jvm_old_size_bytes gauge
+ jvm_old_size_bytes{type="used"} 3522435544
+ jvm_old_size_bytes{type="peak_used"} 6561017832
+ jvm_old_size_bytes{type="max"} 30064771072
+ # HELP jvm_direct_buffer_pool_size_bytes jvm direct buffer pool stat
+ # TYPE jvm_direct_buffer_pool_size_bytes gauge
+ jvm_direct_buffer_pool_size_bytes{type="count"} 91
+ jvm_direct_buffer_pool_size_bytes{type="used"} 226135222
+ jvm_direct_buffer_pool_size_bytes{type="capacity"} 226135221
+ # HELP jvm_young_gc jvm young gc stat
+ # TYPE jvm_young_gc gauge
+ jvm_young_gc{type="count"} 2186
+ jvm_young_gc{type="time"} 93650
+ # HELP jvm_old_gc jvm old gc stat
+ # TYPE jvm_old_gc gauge
+ jvm_old_gc{type="count"} 21
+ jvm_old_gc{type="time"} 58268
+ # HELP jvm_thread jvm thread stat
+ # TYPE jvm_thread gauge
+ jvm_thread{type="count"} 767
+ jvm_thread{type="peak_count"} 831
+ ...
+ ```
+
+这是一个以 [Promethus 格式](https://prometheus.io/docs/practices/naming/) 呈现的监控数据。我们以其中一个监控项为例进行说明:
+
+```
+# HELP jvm_heap_size_bytes jvm heap stat
+# TYPE jvm_heap_size_bytes gauge
+jvm_heap_size_bytes{type="max"} 41661235200
+jvm_heap_size_bytes{type="committed"} 19785285632
+jvm_heap_size_bytes{type="used"} 10113221064
+```
+
+1. "#" 开头的行为注释行。其中 HELP 为该监控项的描述说明;TYPE 表示该监控项的数据类型,示例中为 Gauge,即标量数据。还有 Counter、Histogram 等数据类型。具体可见 [Prometheus 官方文档](https://prometheus.io/docs/practices/instrumentation/#counter-vs.-gauge,-summary-vs.-histogram) 。
+2. `jvm_heap_size_bytes` 即监控项的名称(Key);`type="max"` 即为一个名为 `type` 的 Label,值为 `max`。一个监控项可以有多个 Label。
+3. 最后的数字,如 `41661235200`,即为监控数值。
+
+## 监控架构
+
+整个监控架构如下图所示:
+
+
+
+1. 黄色部分为 Prometheus 相关组件。Prometheus Server 为 Prometheus 的主进程,目前 Prometheus 通过 Pull 的方式访问 Doris 节点的监控接口,然后将时序数据存入时序数据库 TSDB 中(TSDB 包含在 Prometheus 进程中,无需单独部署)。Prometheus 也支持通过搭建 [Push Gateway](https://github.com/prometheus/pushgateway) 的方式,允许被监控系统将监控数据通过 Push 的方式推到 Push Gateway, 再由 Prometheus Server 通过 Pull 的方式从 Push Gateway 中获取数据。
+2. [Alert Manager](https://github.com/prometheus/alertmanager) 为 Prometheus 报警组件,需单独部署(暂不提供方案,可参照官方文档自行搭建)。通过 Alert Manager,用户可以配置报警策略,接收邮件、短信等报警。
+3. 绿色部分为 Grafana 相关组件。Grafana Server 为 Grafana 的主进程。启动后,用户可以通过 Web 页面对 Grafana 进行配置,包括数据源的设置、用户设置、Dashboard 绘制等。这里也是最终用户查看监控数据的地方。
+
+
+## 开始搭建
+
+请在完成 Doris 的部署后,开始搭建监控系统。
+
+### Prometheus
+
+1. 在 [Prometheus 官网](https://prometheus.io/download/) 下载最新版本的 Prometheus。这里我们以 2.3.2-linux-amd64 版本为例。
+2. 在准备运行监控服务的机器上,解压下载后的 tar 文件。
+3. 打开配置文件 promethues.yml。这里我们提供一个示例配置并加以说明(配置文件为 yml 格式,一定注意统一的缩进和空格):
+
+ 这里我们使用最简单的静态文件的方式进行监控配置。Prometheus 支持多种 [服务发现](https://prometheus.io/docs/prometheus/latest/configuration/configuration/) 方式,可以动态的感知节点的加入和删除。
+
+ ```
+ # my global config
+ global:
+ scrape_interval: 15s # 全局的采集间隔,默认是 1m,这里设置为 15s
+ evaluation_interval: 15s # 全局的规则触发间隔,默认是 1m,这里设置 15s
+
+ # Alertmanager configuration
+ alerting:
+ alertmanagers:
+ - static_configs:
+ - targets:
+ # - alertmanager:9093
+
+ # A scrape configuration containing exactly one endpoint to scrape:
+ # Here it's Prometheus itself.
+ scrape_configs:
+ # The job name is added as a label `job=