中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

clickhouse基礎知識總結

發布時間:2021-07-06 18:19:29 來源:億速云 閱讀:222 作者:chen 欄目:大數據

這篇文章主要講解了“clickhouse基礎知識總結”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“clickhouse基礎知識總結”吧!

Clickhouse是一個用于聯機分析處理(OLAP)的列式數據庫管理系統(columnar DBMS)。
傳統數據庫在數據大小比較小,索引大小適合內存,數據緩存命中率足夠高的情形下能正常提供服務。但殘酷的是,這種理想情形最終會隨著業務的增長走到盡頭,查詢會變得越來越慢。你可能通過增加更多的內存,訂購更快的磁盤等等來解決問題(縱向擴展),但這只是拖延解決本質問題。如果你的需求是解決怎樣快速查詢出結果,那么ClickHouse也許可以解決你的問題。

應用場景:
1.絕大多數請求都是用于讀訪問的
2.數據需要以大批次(大于1000行)進行更新,而不是單行更新;或者根本沒有更新操作
3.數據只是添加到數據庫,沒有必要修改
4.讀取數據時,會從數據庫中提取出大量的行,但只用到一小部分列
5.表很“寬”,即表中包含大量的列
6.查詢頻率相對較低(通常每臺服務器每秒查詢數百次或更少)
7.對于簡單查詢,允許大約50毫秒的延遲
8.列的值是比較小的數值和短字符串(例如,每個URL只有60個字節)
9.在處理單個查詢時需要高吞吐量(每臺服務器每秒高達數十億行)
10.不需要事務
11.數據一致性要求較低
12.每次查詢中只會查詢一個大表。除了一個大表,其余都是小表
13.查詢結果顯著小于數據源。即數據有過濾或聚合。返回結果不超過單個服務器內存大小

相應地,使用ClickHouse也有其本身的限制:

1.不支持真正的刪除/更新支持 不支持事務(期待后續版本支持)
2.不支持二級索引
3.有限的SQL支持,join實現與眾不同
4.不支持窗口功能
5.元數據管理需要人工干預維護


常用SQL語法

-- 列出數據庫列表
show databases;

-- 列出數據庫中表列表
show tables;

-- 創建數據庫
create database test;

-- 刪除一個表
drop table if exists test.t1;

-- 創建第一個表
create /*temporary*/ table /*if not exists*/ test.m1 (
 id UInt16
,name String
) ENGINE = Memory
;
-- 插入測試數據
insert into test.m1 (id, name) values (1, 'abc'), (2, 'bbbb');

-- 查詢
select * from test.m1;

默認值


默認值 的處理方面, ClickHouse 中,默認值總是有的,如果沒有顯示式指定的話,會按字段類型處理:

數字類型, 0
字符串,空字符串
數組,空數組
日期, 0000-00-00
時間, 0000-00-00 00:00:00
注:NULLs 是不支持的

數據類型


1.整型:UInt8,UInt16,UInt32,UInt64,Int8,Int16,Int32,Int64
范圍U開頭-2N/2~2N-1;非U開頭0~2^N-1
2.枚舉類型:Enum8,Enum16
Enum('hello'=1,'test'=-1),Enum是有符號的整型映射的,因此負數也是可以的
3.字符串型:FixedString(N),String
N是最大字節數,不是字符長度,如果是UTF8字符串,那么就會占3個字節,GBK會占2字節;String可以用來替換VARCHAR,BLOB,CLOB等數據類型
4.時間類型:Date
5.數組類型:Array(T)
T是一個基本類型,包括arry在內,官方不建議使用多維數組
6.元組:Tuple
7.結構:Nested(name1 Type1,name2 Type2,...)
類似一種map的結

物化列


指定 MATERIALIZED 表達式,即將一個列作為物化列處理了,這意味著這個列的值不能從insert 語句獲取,只能是自己計算出來的。同時,
物化列也不會出現在 select * 的結果中:

drop table if exists test.m2;
create table test.m2 (
 a MATERIALIZED (b+1)
,b UInt16
) ENGINE = Memory;
insert into test.m2 (b) values (1);
select * from test.m2;
select a, b from test.m2;

表達式列


ALIAS 表達式列某方面跟物化列相同,就是它的值不能從 insert 語句獲取。不同的是, 物化列 是會真正保存數據(這樣查詢時不需要再計算),
而表達式列不會保存數據(這樣查詢時總是需要計算),只是在查詢時返回表達式的結果。

create table test.m3 (a ALIAS (b+1), b UInt16) ENGINE = Memory;
insert into test.m3(b) values (1);
select * from test.m3;
select a, b from test.m3;

引擎/engine

引擎是clickhouse設計的精華部分

TinyLog


最簡單的一種引擎,每一列保存為一個文件,里面的內容是壓縮過的,不支持索引
這種引擎沒有并發控制,所以,當你需要在讀,又在寫時,讀會出錯。并發寫,內容都會壞掉。

應用場景:
a. 基本上就是那種只寫一次
b. 然后就是只讀的場景。
c. 不適用于處理量大的數據,官方推薦,使用這種引擎的表最多 100 萬行的數據

drop table if exists test.tinylog;
create table test.tinylog (a UInt16, b UInt16) ENGINE = TinyLog;
insert into test.tinylog(a,b) values (7,13);

此時/var/lib/clickhouse/data/test/tinylog保存數據的目錄結構:

├── a.bin
├── b.bin
└── sizes.json

a.bin 和 b.bin 是壓縮過的對應的列的數據, sizes.json 中記錄了每個 *.bin 文件的大小

Log


這種引擎跟 TinyLog 基本一致
它的改進點,是加了一個 __marks.mrk 文件,里面記錄了每個數據塊的偏移
這樣做的一個用處,就是可以準確地切分讀的范圍,從而使用并發讀取成為可能
但是,它是不能支持并發寫的,一個寫操作會阻塞其它讀寫操作
Log 不支持索引,同時因為有一個 __marks.mrk 的冗余數據,所以在寫入數據時,一旦出現問題,這個表就廢了

應用場景:
同 TinyLog 差不多,它適用的場景也是那種寫一次之后,后面就是只讀的場景,臨時數據用它保存也可以

drop table if exists test.log;
create table test.log (a UInt16, b UInt16) ENGINE = Log;
insert into test.log(a,b) values (7,13);

此時/var/lib/clickhouse/data/test/log保存數據的目錄結構:

├── __marks.mrk
├── a.bin
├── b.bin
└── sizes.json

Memory


內存引擎,數據以未壓縮的原始形式直接保存在內存當中,服務器重啟數據就會消失
可以并行讀,讀寫互斥鎖的時間也非常短
不支持索引,簡單查詢下有非常非常高的性能表現

應用場景:
a. 進行測試
b. 在需要非常高的性能,同時數據量又不太大(上限大概 1 億行)的場景

Merge


一個工具引擎,本身不保存數據,只用于把指定庫中的指定多個表鏈在一起。
這樣,讀取操作可以并發執行,同時也可以利用原表的索引,但是,此引擎不支持寫操作
指定引擎的同時,需要指定要鏈接的庫及表,庫名可以使用一個表達式,表名可以使用正則表達式指定

create table test.tinylog1 (id UInt16, name String) ENGINE=TinyLog;
create table test.tinylog2 (id UInt16, name String) ENGINE=TinyLog;
create table test.tinylog3 (id UInt16, name String) ENGINE=TinyLog;

insert into test.tinylog1(id, name) values (1, 'tinylog1');
insert into test.tinylog2(id, name) values (2, 'tinylog2');
insert into test.tinylog3(id, name) values (3, 'tinylog3');

use test;
create table test.merge (id UInt16, name String) ENGINE=Merge(currentDatabase(), '^tinylog[0-9]+');
select _table,* from test.merge order by id desc

┌─_table───┬─id─┬─name─────┐
│ tinylog3 │ 3 │ tinylog3 │
│ tinylog2 │ 2 │ tinylog2 │
│ tinylog1 │ 1 │ tinylog1 │
└──────────┴────┴──────────┘

注:_table 這個列,是因為使用了 Merge 多出來的一個的一個虛擬列

a. 它表示原始數據的來源表,它不會出現在 show table 的結果當中
b. select * 不會包含它

Distributed


與 Merge 類似, Distributed 也是通過一個邏輯表,去訪問各個物理表,設置引擎時的樣子是:

Distributed(remote_group, database, table [, sharding_key])

其中:

remote_group /etc/clickhouse-server/config.xml中remote_servers參數
database 是各服務器中的庫名
table 是表名
sharding_key 是一個尋址表達式,可以是一個列名,也可以是像 rand() 之類的函數調用,它與 remote_servers 中的 weight 共同作用,決定在 寫 時往哪個 shard 寫

配置文件中的 remote_servers

<remote_servers>
   <log>
       <shard>
           <weight>1</weight>
           <internal_replication>false</internal_replication>
           <replica>
               <host>172.17.0.3</host>
               <port>9000</port>
           </replica>
       </shard>
       <shard>
           <weight>2</weight>
           <internal_replication>false</internal_replication>
           <replica>
               <host>172.17.0.4</host>
               <port>9000</port>
           </replica>
       </shard>
   </log>
</remote_servers>

log 是某個 shard 組的名字,就是上面的 remote_group 的值
shard 是固定標簽
weight 是權重,前面說的 sharding_key 與這個有關。
簡單來說,上面的配置,理論上來看:
第一個 shard “被選中”的概率是 1 / (1 + 2) ,第二個是 2 / (1 + 2) ,這很容易理解。但是, sharding_key 的工作情況,是按實際數字的“命中區間”算的,即第一個的區間是 [0, 1) 的周期,第二個區間是 [1, 1+2) 的周期。比如把 sharding_key 設置成 id ,當 id=0 或 id=3 時,一定是寫入到第一個 shard 中,如果把 sharding_key 設置成 rand() ,那系統會對應地自己作一般化轉換吧,這種時候就是一種概率場景了。
internal_replication 是定義針對多個 replica 時的寫入行為的。
如果為 false ,則會往所有的 replica 中寫入數據,但是并不保證數據寫入的一致性,所以這種情況時間一長,各 replica 的數據很可能出現差異。如果為 true ,則只會往第一個可寫的 replica 中寫入數據(剩下的事“物理表”自己處理)。
replica 就是定義各個冗余副本的,選項有 host , port , user , password 等

看一個實際的例子,我們先在兩臺機器上創建好物理表并插入一些測試數據:

create table test.tinylog_d1(id UInt16, name String) ENGINE=TinyLog;
insert into test.tinylog_d1(id, name) values (1, 'Distributed record 1');
insert into test.tinylog_d1(id, name) values (2, 'Distributed record 2');

在其中一臺創建邏輯表:

create table test.tinylog_d (id UInt16, name String) ENGINE=Distributed(log, test,tinylog_d1 , id);

-- 插入數據到邏輯表,觀察數據分發情況
insert into test.tinylog_d(id, name) values (0, 'main');
insert into test.tinylog_d(id, name) values (1, 'main');
insert into test.tinylog_d(id, name) values (2, 'main');

select name,sum(id),count(id) from test.tinylog_d group by name;

注:邏輯表中的寫入操作是異步的,會先緩存在本機的文件系統上,并且,對于物理表的不可訪問狀態,并沒有嚴格控制,所以寫入失敗丟數據的情況是可能發生的

Null


空引擎,寫入的任何數據都會被忽略,讀取的結果一定是空。

但是注意,雖然數據本身不會被存儲,但是結構上的和數據格式上的約束還是跟普通表一樣是存在的,同時,你也可以在這個引擎上創建視圖

Buffer


1.Buffer 引擎,像是Memory 存儲的一個上層應用似的(磁盤上也是沒有相應目錄的)
2.它的行為是一個緩沖區,寫入的數據先被放在緩沖區,達到一個閾值后,這些數據會自動被寫到指定的另一個表中
3.和Memory 一樣,有很多的限制,比如沒有索引
4.Buffer 是接在其它表前面的一層,對它的讀操作,也會自動應用到后面表,但是因為前面說到的限制的原因,一般我們讀數據,就直接從源表讀就好了,緩沖區的這點數據延遲,只要配置得當,影響不大的
5.Buffer 后面也可以不接任何表,這樣的話,當數據達到閾值,就會被丟棄掉

一些特點:

  • 如果一次寫入的數據太大或太多,超過了 max 條件,則會直接寫入源表。

  • 刪源表或改源表的時候,建議 Buffer 表刪了重建。

  • “友好重啟”時, Buffer 數據會先落到源表,“暴力重啟”, Buffer 表中的數據會丟失。

  • 即使使用了 Buffer ,多次的小數據寫入,對比一次大數據寫入,也 慢得多 (幾千行與百萬行的差距)

-- 創建源表
create table test.mergetree (sdt  Date, id UInt16, name String, point UInt16) ENGINE=MergeTree(sdt, (id, name), 10);
-- 創建 Buffer表
-- Buffer(database, table, num_layers, min_time, max_time, min_rows, max_rows, min_bytes, max_bytes)
create table test.mergetree_buffer as test.mergetree ENGINE=Buffer(test, mergetree, 16, 3, 20, 2, 10, 1, 10000);

insert into test.mergetree (sdt, id, name, point) values ('2017-07-10', 1, 'a', 20);
insert into test.mergetree_buffer (sdt, id, name, point) values ('2017-07-10', 1, 'b', 10);
select * from test.mergetree;
select '------';
select * from test.mergetree_buffer;

database 數據庫
table 源表,這里除了字符串常量,也可以使用變量的。
num_layers 是類似“分區”的概念,每個分區的后面的 min / max 是獨立計算的,官方推薦的值是 16 。
min / max 這組配置薦,就是設置閾值的,分別是 時間(秒),行數,空間(字節)。

閾值的規則: 是“所有的 min 條件都滿足, 或 至少一個 max 條件滿足”。

如果按上面我們的建表來說,所有的 min 條件就是:過了 3秒,2條數據,1 Byte。一個 max 條件是:20秒,或 10 條數據,或有 10K

Set


Set 這個引擎有點特殊,因為它只用在 IN 操作符右側,你不能對它 select

create table test.set(id UInt16, name String) ENGINE=Set;
insert into test.set(id, name) values (1, 'hello');
-- select 1 where (1, 'hello') in test.set; -- 默認UInt8 需要手動進行類型轉換
select 1 where (toUInt16(1), 'hello') in test.set;

注: Set 引擎表,是全內存運行的,但是相關數據會落到磁盤上保存,啟動時會加載到內存中。所以,意外中斷或暴力重啟,是可能產生數據丟失問題的

Join


TODO

MergeTree


這個引擎是 ClickHouse 的重頭戲,它支持一個日期和一組主鍵的兩層式索引,還可以實時更新數據。同時,索引的粒度可以自定義,外加直接支持采樣功能

MergeTree(EventDate, (CounterID, EventDate), 8192)
MergeTree(EventDate, intHash42(UserID), (CounterID, EventDate, intHash42(UserID)), 8192)

EventDate 一個日期的列名
intHash42(UserID) 采樣表達式
(CounterID, EventDate) 主鍵組(里面除了列名,也支持表達式),也可以是一個表達式
8192 主鍵索引的粒度

drop table if exists test.mergetree1;
create table test.mergetree1 (sdt  Date, id UInt16, name String, cnt UInt16) ENGINE=MergeTree(sdt, (id, name), 10);

-- 日期的格式,好像必須是 yyyy-mm-dd
insert into test.mergetree1(sdt, id, name, cnt) values ('2018-06-01', 1, 'aaa', 10);
insert into test.mergetree1(sdt, id, name, cnt) values ('2018-06-02', 4, 'bbb', 10);
insert into test.mergetree1(sdt, id, name, cnt) values ('2018-06-03', 5, 'ccc', 11);

此時/var/lib/clickhouse/data/test/mergetree1的目錄結構:

├── 20180601_20180601_1_1_0
│   ├── checksums.txt
│   ├── columns.txt
│   ├── id.bin
│   ├── id.mrk
│   ├── name.bin
│   ├── name.mrk
│   ├── cnt.bin
│   ├── cnt.mrk 
│   ├── cnt.idx
│   ├── primary.idx
│   ├── sdt.bin
│   └── sdt.mrk -- 保存一下塊偏移量
├── 20180602_20180602_2_2_0
│   └── ...
├── 20180603_20180603_3_3_0
│   └── ...
├── format_version.txt
└── detached

ReplacingMergeTree

1.在 MergeTree 的基礎上,添加了“處理重復數據”的功能=>實時數據場景
2.相比 MergeTree ,ReplacingMergeTree 在最后加一個"版本列",它跟時間列配合一起,用以區分哪條數據是"新的",并把舊的丟掉(這個過程是在 merge 時處理,不是數據寫入時就處理了的,平時重復的數據還是保存著的,并且查也是跟平常一樣會查出來的)
3.主鍵列組用于區分重復的行

-- 版本列 允許的類型是, UInt 一族的整數,或 Date 或 DateTime
create table test.replacingmergetree (sdt  Date, id UInt16, name String, cnt UInt16) ENGINE=ReplacingMergeTree(sdt, (name), 10, cnt);

insert into test.replacingmergetree (sdt, id, name, cnt) values ('2018-06-10', 1, 'a', 20);
insert into test.replacingmergetree (sdt, id, name, cnt) values ('2018-06-10', 1, 'a', 30);
insert into test.replacingmergetree (sdt, id, name, cnt) values ('2018-06-11', 1, 'a', 20);
insert into test.replacingmergetree (sdt, id, name, cnt) values ('2018-06-11', 1, 'a', 30);
insert into test.replacingmergetree (sdt, id, name, cnt) values ('2018-06-11', 1, 'a', 10);

select * from test.replacingmergetree;

-- 如果記錄未執行merge,可以手動觸發一下 merge 行為
optimize table test.replacingmergetree;

┌────────sdt─┬─id─┬─name─┬─cnt─┐
│ 2018-06-11 │ 1 │ a │ 30 │
└────────────┴────┴──────┴─────┘

SummingMergeTree


1.SummingMergeTree 就是在 merge 階段把數據sum求和
2.sum求和的列可以指定,不可加的未指定列,會取一個最先出現的值

create table test.summingmergetree (sdt Date, name String, a UInt16, b UInt16) ENGINE=SummingMergeTree(sdt, (sdt, name), 8192, (a));

insert into test.summingmergetree (sdt, name, a, b) values ('2018-06-10', 'a', 1, 20);
insert into test.summingmergetree (sdt, name, a, b) values ('2018-06-10', 'b', 2, 11);
insert into test.summingmergetree (sdt, name, a, b) values ('2018-06-11', 'b', 3, 18);
insert into test.summingmergetree (sdt, name, a, b) values ('2018-06-11', 'b', 3, 82);
insert into test.summingmergetree (sdt, name, a, b) values ('2018-06-11', 'a', 3, 11);
insert into test.summingmergetree (sdt, name, a, b) values ('2018-06-12', 'c', 1, 35);

-- 手動觸發一下 merge 行為
optimize table test.summingmergetree;

select * from test.summingmergetree;

┌────────sdt─┬─name─┬─a─┬──b─┐
│ 2018-06-10 │ a │ 1 │ 20 │
│ 2018-06-10 │ b │ 2 │ 11 │
│ 2018-06-11 │ a │ 3 │ 11 │
│ 2018-06-11 │ b │ 6 │ 18 │
│ 2018-06-12 │ c │ 1 │ 35 │
└────────────┴──────┴───┴────┘
注: 可加列不能是主鍵中的列,并且如果某行數據可加列都是 null ,則這行會被刪除

AggregatingMergeTree


AggregatingMergeTree 是在 MergeTree 基礎之上,針對聚合函數結果,作增量計算優化的一個設計,它會在 merge 時,針對主鍵預處理聚合的數據
應用于AggregatingMergeTree 上的聚合函數除了普通的 sum, uniq等,還有 sumState , uniqState ,及 sumMerge , uniqMerge 這兩組

1.聚合數據的預計算
是一種“空間換時間”的權衡,并且是以減少維度為代價的

dim1dim2dim3measure1
aaaaa11
aaaab21
bbbbb31
ccccb21
ccccc11
ddddc21
dddda11

假設原始有三個維度,一個需要 count 的指標

dim1dim2dim3measure1
aaaaa11
aaaab21
bbbbb31
ccccb21
ccccc11
ddddc21
dddda11

通過減少一個維度的方式,來以 count 函數聚合一次 M

dim2dim3count(measure1)
a13
b22
b31
c11
c21

2.聚合數據的增量計算

對于 AggregatingMergeTree 引擎的表,不能使用普通的 INSERT 去添加數據,可以用:
a. INSERT SELECT 來插入數據
b. 更常用的,是可以創建一個物化視圖

drop table if exists test.aggregatingmergetree;
create table test.aggregatingmergetree(
sdt Date
, dim1 String
, dim2 String
, dim3 String
, measure1 UInt64
) ENGINE=MergeTree(sdt, (sdt, dim1, dim2, dim3), 8192);

-- 創建一個物化視圖,使用 AggregatingMergeTree
drop table if exists test.aggregatingmergetree_view;
create materialized view test.aggregatingmergetree_view
ENGINE = AggregatingMergeTree(sdt,(dim2, dim3), 8192)
as
select sdt,dim2, dim3, uniqState(dim1) as uv
from test.aggregatingmergetree
group by sdt,dim2, dim3;

insert into test.aggregatingmergetree (sdt, dim1, dim2, dim3, measure1) values ('2018-06-10', 'aaaa', 'a', '10', 1);
insert into test.aggregatingmergetree (sdt, dim1, dim2, dim3, measure1) values ('2018-06-10', 'aaaa', 'a', '10', 1);
insert into test.aggregatingmergetree (sdt, dim1, dim2, dim3, measure1) values ('2018-06-10', 'aaaa', 'b', '20', 1);
insert into test.aggregatingmergetree (sdt, dim1, dim2, dim3, measure1) values ('2018-06-10', 'bbbb', 'b', '30', 1);
insert into test.aggregatingmergetree (sdt, dim1, dim2, dim3, measure1) values ('2018-06-10', 'cccc', 'b', '20', 1);
insert into test.aggregatingmergetree (sdt, dim1, dim2, dim3, measure1) values ('2018-06-10', 'cccc', 'c', '10', 1);
insert into test.aggregatingmergetree (sdt, dim1, dim2, dim3, measure1) values ('2018-06-10', 'dddd', 'c', '20', 1);
insert into test.aggregatingmergetree (sdt, dim1, dim2, dim3, measure1) values ('2018-06-10', 'dddd', 'a', '10', 1);

-- 按 dim2 和 dim3 聚合 count(measure1)
select dim2, dim3, count(measure1) from test.aggregatingmergetree group by dim2, dim3;

-- 按 dim2 聚合 UV
select dim2, uniq(dim1) from test.aggregatingmergetree group by dim2;

-- 手動觸發merge
OPTIMIZE TABLE test.aggregatingmergetree_view;
select * from test.aggregatingmergetree_view;

-- 查 dim2 的 uv
select dim2, uniqMerge(uv) from test.aggregatingmergetree_view group by dim2 order by dim2;

CollapsingMergeTree

是專門為 OLAP 場景下,一種“變通”存數做法而設計的,在數據是不能改,更不能刪的前提下,通過“運算”的方式,去抹掉舊數據的影響,把舊數據“減”去即可,從而解決"最終狀態"類的問題,比如 當前有多少人在線?

“以加代刪”的增量存儲方式,帶來了聚合計算方便的好處,代價卻是存儲空間的翻倍,并且,對于只關心最新狀態的場景,中間數據都是無用的

CollapsingMergeTree 在創建時與 MergeTree 基本一樣,除了最后多了一個參數,需要指定 Sign 位(必須是 Int8 類型)

create table test.collapsingmergetree(sign Int8, sdt Date, name String, cnt UInt16) ENGINE=CollapsingMergeTree(sdt, (sdt, name), 8192, sign);

感謝各位的閱讀,以上就是“clickhouse基礎知識總結”的內容了,經過本文的學習后,相信大家對clickhouse基礎知識總結這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

伊金霍洛旗| 锦州市| 东阿县| 武陟县| 康马县| 囊谦县| 简阳市| 新乡市| 新沂市| 仪征市| 岗巴县| 金寨县| 宕昌县| 东乌珠穆沁旗| 文水县| 工布江达县| 连平县| 阜宁县| 峨眉山市| 霍林郭勒市| 龙州县| 木里| 兰西县| 蓝山县| 类乌齐县| 本溪| 宾阳县| 田阳县| 石城县| 荔浦县| 当涂县| 文登市| 化德县| 比如县| 九江市| 柏乡县| 青神县| 新余市| 绥江县| 靖江市| 湘乡市|