PostgreSQL 统计信息混淆之处(scan,read,fetch,hit)源码解读
2016 Postgres大象会官方报名通道: 点此报名
作者: digoal
日期: 2016-03-18
PostgreSQL 几个统计信息的解释难以理解,所以本文花一些时间从源码的角度来解释一下。 让大家对这几个容易误解的统计值有更好的理解。
比较难理解的几个统计值为:
pg_stat_all_indexes 的
idx_scan idx_tup_read idx_tup_fetch
pg_statio_all_indexes 的
idx_blks_read idx_blks_hit
pg_stat_all_tables 的
seq_scan seq_tup_read idx_scan idx_tup_fetch
pg_statio_all_tables 的
heap_blks_read heap_blks_hit idx_blks_read idx_blks_hit toast_blks_read heap表对应的toast表统计字段 toast_blks_hit tidx_blks_read heap表的索引对应的toast索引统计字段 tidx_blks_hit
首先需要获得以上统计字段的信息来源:
postgres=# \d+ pg_stat_all_indexes View "pg_catalog.pg_stat_all_indexes" Column | Type | Modifiers | Storage | Description ---------------+--------+-----------+---------+------------- relid | oid | | plain | indexrelid | oid | | plain | schemaname | name | | plain | relname | name | | plain | indexrelname | name | | plain | idx_scan | bigint | | plain | --pg_stat_get_numscans(i.oid) idx_tup_read | bigint | | plain | --pg_stat_get_tuples_returned(i.oid) idx_tup_fetch | bigint | | plain | --pg_stat_get_tuples_fetched(i.oid) View definition: SELECT c.oid AS relid, i.oid AS indexrelid, n.nspname AS schemaname, c.relname, i.relname AS indexrelname, pg_stat_get_numscans(i.oid) AS idx_scan, pg_stat_get_tuples_returned(i.oid) AS idx_tup_read, pg_stat_get_tuples_fetched(i.oid) AS idx_tup_fetch FROM pg_class c JOIN pg_index x ON c.oid = x.indrelid JOIN pg_class i ON i.oid = x.indexrelid LEFT JOIN pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind = ANY (ARRAY['r'::"char", 't'::"char", 'm'::"char"]);
postgres=# \d+ pg_statio_all_indexes View "pg_catalog.pg_statio_all_indexes" Column | Type | Modifiers | Storage | Description ---------------+--------+-----------+---------+------------- relid | oid | | plain | indexrelid | oid | | plain | schemaname | name | | plain | relname | name | | plain | indexrelname | name | | plain | idx_blks_read | bigint | | plain | -- pg_stat_get_blocks_fetched(i.oid) - pg_stat_get_blocks_hit(i.oid) idx_blks_hit | bigint | | plain | -- pg_stat_get_blocks_hit(i.oid)
View definition:
SELECT c.oid AS relid, i.oid AS indexrelid, n.nspname AS schemaname, c.relname, i.relname AS indexrelname, pg_stat_get_blocks_fetched(i.oid) - pg_stat_get_blocks_hit(i.oid) AS idx_blks_read, pg_stat_get_blocks_hit(i.oid) AS idx_blks_hit FROM pg_class c JOIN pg_index x ON c.oid = x.indrelid JOIN pg_class i ON i.oid = x.indexrelid LEFT JOIN pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind = ANY (ARRAY['r'::"char", 't'::"char", 'm'::"char"]);
postgres=# \d+ pg_stat_all_tables View "pg_catalog.pg_stat_all_tables" Column | Type | Modifiers | Storage | Description ---------------------+--------------------------+-----------+---------+------------- relid | oid | | plain | schemaname | name | | plain | relname | name | | plain | seq_scan | bigint | | plain | -- pg_stat_get_numscans(c.oid) seq_tup_read | bigint | | plain | -- pg_stat_get_tuples_returned(c.oid) idx_scan | bigint | | plain | -- sum(pg_stat_get_numscans(i.indexrelid)) idx_tup_fetch | bigint | | plain | -- sum(pg_stat_get_tuples_fetched(i.indexrelid)) + pg_stat_get_tuples_fetched(c.oid) n_tup_ins | bigint | | plain | n_tup_upd | bigint | | plain | n_tup_del | bigint | | plain | n_tup_hot_upd | bigint | | plain | n_live_tup | bigint | | plain | n_dead_tup | bigint | | plain | n_mod_since_analyze | bigint | | plain | last_vacuum | timestamp with time zone | | plain | last_autovacuum | timestamp with time zone | | plain | last_analyze | timestamp with time zone | | plain | last_autoanalyze | timestamp with time zone | | plain | vacuum_count | bigint | | plain | autovacuum_count | bigint | | plain | analyze_count | bigint | | plain | autoanalyze_count | bigint | | plain | View definition: SELECT c.oid AS relid, n.nspname AS schemaname, c.relname, pg_stat_get_numscans(c.oid) AS seq_scan, pg_stat_get_tuples_returned(c.oid) AS seq_tup_read, sum(pg_stat_get_numscans(i.indexrelid))::bigint AS idx_scan, sum(pg_stat_get_tuples_fetched(i.indexrelid))::bigint + pg_stat_get_tuples_fetched(c.oid) AS idx_tup_fetch, pg_stat_get_tuples_inserted(c.oid) AS n_tup_ins, pg_stat_get_tuples_updated(c.oid) AS n_tup_upd, pg_stat_get_tuples_deleted(c.oid) AS n_tup_del, pg_stat_get_tuples_hot_updated(c.oid) AS n_tup_hot_upd, pg_stat_get_live_tuples(c.oid) AS n_live_tup, pg_stat_get_dead_tuples(c.oid) AS n_dead_tup, pg_stat_get_mod_since_analyze(c.oid) AS n_mod_since_analyze, pg_stat_get_last_vacuum_time(c.oid) AS last_vacuum, pg_stat_get_last_autovacuum_time(c.oid) AS last_autovacuum, pg_stat_get_last_analyze_time(c.oid) AS last_analyze, pg_stat_get_last_autoanalyze_time(c.oid) AS last_autoanalyze, pg_stat_get_vacuum_count(c.oid) AS vacuum_count, pg_stat_get_autovacuum_count(c.oid) AS autovacuum_count, pg_stat_get_analyze_count(c.oid) AS analyze_count, pg_stat_get_autoanalyze_count(c.oid) AS autoanalyze_count FROM pg_class c LEFT JOIN pg_index i ON c.oid = i.indrelid LEFT JOIN pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind = ANY (ARRAY['r'::"char", 't'::"char", 'm'::"char"]) GROUP BY c.oid, n.nspname, c.relname;
postgres=# \d+ pg_statio_all_tables View "pg_catalog.pg_statio_all_tables" Column | Type | Modifiers | Storage | Description -----------------+--------+-----------+---------+------------- relid | oid | | plain | schemaname | name | | plain | relname | name | | plain | heap_blks_read | bigint | | plain | -- pg_stat_get_blocks_fetched(c.oid) - pg_stat_get_blocks_hit(c.oid) heap_blks_hit | bigint | | plain | -- pg_stat_get_blocks_hit(c.oid) idx_blks_read | bigint | | plain | -- sum(pg_stat_get_blocks_fetched(i.indexrelid) - pg_stat_get_blocks_hit(i.indexrelid)) idx_blks_hit | bigint | | plain | -- sum(pg_stat_get_blocks_hit(i.indexrelid)) toast_blks_read | bigint | | plain | -- pg_stat_get_blocks_fetched(t.oid) - pg_stat_get_blocks_hit(t.oid) toast_blks_hit | bigint | | plain | -- pg_stat_get_blocks_hit(t.oid) tidx_blks_read | bigint | | plain | -- sum(pg_stat_get_blocks_fetched(x.indexrelid) - pg_stat_get_blocks_hit(x.indexrelid)) tidx_blks_hit | bigint | | plain | -- sum(pg_stat_get_blocks_hit(x.indexrelid)) View definition: SELECT c.oid AS relid, n.nspname AS schemaname, c.relname, pg_stat_get_blocks_fetched(c.oid) - pg_stat_get_blocks_hit(c.oid) AS heap_blks_read, pg_stat_get_blocks_hit(c.oid) AS heap_blks_hit, sum(pg_stat_get_blocks_fetched(i.indexrelid) - pg_stat_get_blocks_hit(i.indexrelid))::bigint AS idx_blks_read, sum(pg_stat_get_blocks_hit(i.indexrelid))::bigint AS idx_blks_hit, pg_stat_get_blocks_fetched(t.oid) - pg_stat_get_blocks_hit(t.oid) AS toast_blks_read, pg_stat_get_blocks_hit(t.oid) AS toast_blks_hit, sum(pg_stat_get_blocks_fetched(x.indexrelid) - pg_stat_get_blocks_hit(x.indexrelid))::bigint AS tidx_blks_read, sum(pg_stat_get_blocks_hit(x.indexrelid))::bigint AS tidx_blks_hit FROM pg_class c LEFT JOIN pg_index i ON c.oid = i.indrelid LEFT JOIN pg_class t ON c.reltoastrelid = t.oid LEFT JOIN pg_index x ON t.oid = x.indrelid LEFT JOIN pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind = ANY (ARRAY['r'::"char", 't'::"char", 'm'::"char"]) GROUP BY c.oid, n.nspname, c.relname, t.oid, x.indrelid;
以上几个统计字段的统计信息来自如下函数:
idx_scan | bigint | | plain | -- pg_stat_get_numscans(i.oid) idx_tup_read | bigint | | plain | -- pg_stat_get_tuples_returned(i.oid) idx_tup_fetch | bigint | | plain | -- pg_stat_get_tuples_fetched(i.oid) idx_blks_read | bigint | | plain | -- pg_stat_get_blocks_fetched(i.oid) - pg_stat_get_blocks_hit(i.oid) idx_blks_hit | bigint | | plain | -- pg_stat_get_blocks_hit(i.oid) seq_scan | bigint | | plain | -- pg_stat_get_numscans(c.oid) seq_tup_read | bigint | | plain | -- pg_stat_get_tuples_returned(c.oid) idx_scan | bigint | | plain | -- sum(pg_stat_get_numscans(i.indexrelid)) idx_tup_fetch | bigint | | plain | -- sum(pg_stat_get_tuples_fetched(i.indexrelid)) + pg_stat_get_tuples_fetched(c.oid) heap_blks_read | bigint | | plain | -- pg_stat_get_blocks_fetched(c.oid) - pg_stat_get_blocks_hit(c.oid) heap_blks_hit | bigint | | plain | -- pg_stat_get_blocks_hit(c.oid) idx_blks_read | bigint | | plain | -- sum(pg_stat_get_blocks_fetched(i.indexrelid) - pg_stat_get_blocks_hit(i.indexrelid)) idx_blks_hit | bigint | | plain | -- sum(pg_stat_get_blocks_hit(i.indexrelid)) toast_blks_read | bigint | | plain | -- pg_stat_get_blocks_fetched(t.oid) - pg_stat_get_blocks_hit(t.oid) toast_blks_hit | bigint | | plain | -- pg_stat_get_blocks_hit(t.oid) tidx_blks_read | bigint | | plain | -- sum(pg_stat_get_blocks_fetched(x.indexrelid) - pg_stat_get_blocks_hit(x.indexrelid)) tidx_blks_hit | bigint | | plain | -- sum(pg_stat_get_blocks_hit(x.indexrelid))
这些SQL函数对应的C函数如下:
postgres=# \df+ pg_stat_get_numscans | Source code | Description +----------------------+-------------------------------------------------- | pg_stat_get_numscans | statistics: number of scans done for table/index postgres=# \df+ pg_stat_get_tuples_returned | Source code | Description +-----------------------------+---------------------------------------------- | pg_stat_get_tuples_returned | statistics: number of tuples read by seqscan postgres=# \df+ pg_stat_get_tuples_fetched | Source code | Description +----------------------------+------------------------------------------------- | pg_stat_get_tuples_fetched | statistics: number of tuples fetched by idxscan postgres=# \df+ pg_stat_get_blocks_fetched | Source code | Description +----------------------------+-------------------------------------- | pg_stat_get_blocks_fetched | statistics: number of blocks fetched postgres=# \df+ pg_stat_get_blocks_hit | Source code | Description +------------------------+--------------------------------------------- | pg_stat_get_blocks_hit | statistics: number of blocks found in cache
以上5个C函数的源码分析
pg_stat_get_numscans result = (int64) (tabentry->numscans); pg_stat_get_tuples_returned result = (int64) (tabentry->tuples_returned); pg_stat_get_tuples_fetched result = (int64) (tabentry->tuples_fetched); pg_stat_get_blocks_fetched result = (int64) (tabentry->blocks_fetched); pg_stat_get_blocks_hit result = (int64) (tabentry->blocks_hit);
他们都是返回以下数据结构中的某项计数器的值:
/* ---------- * PgStat_StatTabEntry The collector's data per table (or index) * ---------- */ typedef struct PgStat_StatTabEntry { Oid tableid; PgStat_Counter numscans; PgStat_Counter tuples_returned; PgStat_Counter tuples_fetched; PgStat_Counter tuples_inserted; PgStat_Counter tuples_updated; PgStat_Counter tuples_deleted; PgStat_Counter tuples_hot_updated; PgStat_Counter n_live_tuples; PgStat_Counter n_dead_tuples; PgStat_Counter changes_since_analyze; PgStat_Counter blocks_fetched; PgStat_Counter blocks_hit; TimestampTz vacuum_timestamp; /* user initiated vacuum */ PgStat_Counter vacuum_count; TimestampTz autovac_vacuum_timestamp; /* autovacuum initiated */ PgStat_Counter autovac_vacuum_count; TimestampTz analyze_timestamp; /* user initiated */ PgStat_Counter analyze_count; TimestampTz autovac_analyze_timestamp; /* autovacuum initiated */ PgStat_Counter autovac_analyze_count; } PgStat_StatTabEntry;
这些值是由pgstats进程来进行统计的
PgstatCollectorMain(int argc, char *argv[]) { ... for (;;) { /* Clear any already-pending wakeups */ ResetLatch(&pgStatLatch); ... /* * O.K. - we accept this message. Process it. */ switch (msg.msg_hdr.m_type) { ... case PGSTAT_MTYPE_TABSTAT: pgstat_recv_tabstat((PgStat_MsgTabstat *) &msg, len); break; ... /* ---------- * pgstat_recv_tabstat() - * * Count what the backend has done. * ---------- */ static void pgstat_recv_tabstat(PgStat_MsgTabstat *msg, int len) { ... tabentry->numscans += tabmsg->t_counts.t_numscans; tabentry->tuples_returned += tabmsg->t_counts.t_tuples_returned; tabentry->tuples_fetched += tabmsg->t_counts.t_tuples_fetched; tabentry->tuples_inserted += tabmsg->t_counts.t_tuples_inserted; tabentry->tuples_updated += tabmsg->t_counts.t_tuples_updated; tabentry->tuples_deleted += tabmsg->t_counts.t_tuples_deleted; tabentry->tuples_hot_updated += tabmsg->t_counts.t_tuples_hot_updated; tabentry->n_live_tuples += tabmsg->t_counts.t_delta_live_tuples; tabentry->n_dead_tuples += tabmsg->t_counts.t_delta_dead_tuples; tabentry->changes_since_analyze += tabmsg->t_counts.t_changed_tuples; tabentry->blocks_fetched += tabmsg->t_counts.t_blocks_fetched; tabentry->blocks_hit += tabmsg->t_counts.t_blocks_hit; ...
tabmsg->t_counts.? 则是通过如下macro进行改写的:
/* nontransactional event counts are simple enough to inline */ #define pgstat_count_heap_scan(rel) do { if ((rel)->pgstat_info != NULL) (rel)->pgstat_info->t_counts.t_numscans++; } while (0) #define pgstat_count_heap_getnext(rel) do { if ((rel)->pgstat_info != NULL) (rel)->pgstat_info->t_counts.t_tuples_returned++; } while (0) #define pgstat_count_heap_fetch(rel) do { if ((rel)->pgstat_info != NULL) (rel)->pgstat_info->t_counts.t_tuples_fetched++; } while (0) #define pgstat_count_index_scan(rel) do { if ((rel)->pgstat_info != NULL) (rel)->pgstat_info->t_counts.t_numscans++; } while (0) #define pgstat_count_index_tuples(rel, n) do { if ((rel)->pgstat_info != NULL) (rel)->pgstat_info->t_counts.t_tuples_returned += (n); } while (0) #define pgstat_count_buffer_read(rel) do { if ((rel)->pgstat_info != NULL) (rel)->pgstat_info->t_counts.t_blocks_fetched++; } while (0) #define pgstat_count_buffer_hit(rel) do { if ((rel)->pgstat_info != NULL) (rel)->pgstat_info->t_counts.t_blocks_hit++; } while (0)
取出每个macro对应的调用以及解释如下:
pgstat_count_index_scan(idx_oid)
统计指定索引的扫描次数,和扫描多少条记录无关,和node有个,一般看执行计划中,同一个索引如果在NODE中出现一次,那么就算扫描一次。
pgstat_count_index_tuples(rel, n)
统计从指定索引获取tid的条数
pgstat_count_heap_fetch
统计从使用指定索引的tid获取HEAP tuple的条数
pgstat_count_buffer_read
统计所有的buffer read次数, 包括在postgresql shared buffers中命中的,或者未在postgresql shared buffers中命中的。
pgstat_count_buffer_hit(rel)
统计在shared buffers中命中的buffer read次数。
pgstat_count_heap_scan(rel)
统计指定表的,全表扫描的次数,和返回的记录数无关,只和执行计划中的node相关,如果在plan中某个表只有一个seq scan的次数,则这条SQL执行一次时算一次。
pgstat_count_heap_getnext(rel)
指从全表扫描节点中扫描的记录数
梳理一下最初的统计字段和这些macro的对应关系:
pg_stat_all_indexes 的 idx_scan 对应 pgstat_count_index_scan(idx_oid) 产生的计数的累加 idx_tup_read 对应 pgstat_count_index_tuples(idx_oid, n) 产生的计数的累加 idx_tup_fetch 对应 pgstat_count_heap_fetch(idx_oid) 产生的计数的累加 pg_statio_all_indexes 的 idx_blks_read 对应 pgstat_count_buffer_read(idx_oid) 产生的计数的累加 idx_blks_hit 对应 pgstat_count_buffer_hit(idx_oid) 产生的计数的累加 pg_stat_all_tables 的 seq_scan 对应 pgstat_count_heap_scan(tbl_oid) 产生的计数的累加 seq_tup_read 对应 pgstat_count_heap_getnext(tbl_oid) 产生的计数的累加 idx_scan 对应 sum( 索引 pgstat_count_index_scan(tbl_oid) ) 产生的计数的累加 idx_tup_fetch 对应 sum( 索引 pgstat_count_index_tuples(idx_oid, n) ) + pgstat_count_heap_fetch(tbl_oid) 产生的计数的累加 pg_statio_all_tables 的 heap_blks_read 对应 pgstat_count_buffer_read(tbl_oid) - pgstat_count_buffer_hit(tbl_oid) 产生的计数的累加 heap_blks_hit 对应 pgstat_count_buffer_hit(tbl_oid) 产生的计数的累加 idx_blks_read 对应 sum( 索引 pgstat_count_buffer_read(idx_oid) - pgstat_count_buffer_hit(idx_oid) ) 产生的计数的累加 idx_blks_hit 对应 sum( pgstat_count_buffer_hit(idx_oid) ) 产生的计数的累加 toast_blks_read 对应 pgstat_count_buffer_read(toast_oid) - pgstat_count_buffer_hit(toast_oid) 产生的计数的累加 toast_blks_hit 对应 pgstat_count_buffer_hit(toast_oid) 产生的计数的累加 tidx_blks_read 对应 sum( 索引 pgstat_count_buffer_read(toast_idx_oid) - pgstat_count_buffer_hit(toast_idx_oid) ) 产生的计数的累加 tidx_blks_hit 对应 sum( pgstat_count_buffer_hit(toast_idx_oid) ) 产生的计数的累加
小结:
pg_stat_all_indexes 的
idx_scan 索引被扫描了多少次,和扫描多少条记录无关,和node有关,一般看执行计划, 同一个索引如果在NODE中出现一次,那么这条SQL执行时这个索引就算扫描一次。 idx_tup_read 从指定索引获取tid的条(tid是指向heap表数据块上某条记录的一个数据结构, 如(1,10)表示1号数据块的第10条记录) idx_tup_fetch 从索引的tid获取HEAP tuple的记数(每扫一条tuple计1)
pg_statio_all_indexes 的
idx_blks_read 该索引的buffer read记数(每读一个block记1次), 包括在postgresql shared buffers中命中的, 或者未在postgresql shared buffers中命中的。 idx_blks_hit 在postgresql shared buffers中命中的buffer read记数。
pg_stat_all_tables 的
seq_scan 全表扫描的次数 seq_tup_read 使用全表扫描扫过的tuple条数 idx_scan 该表的所有索引扫描次数总和 idx_tup_fetch 该表的所有 从索引的tid获取HEAP tuple的条数
pg_statio_all_tables 的
heap_blks_read 该表的buffer read记数, 包括在postgresql shared buffers中命中的, 或者未在postgresql shared buffers中命中的。 heap_blks_hit 在postgresql shared buffers中命中的buffer read记数。 idx_blks_read 该表所有索引 所有buffer read记数(含命中和未命中) idx_blks_hit 该表所有索引 在shared buffer命中的buffer read记数 toast_blks_read heap表对应的toast表统计字段 toast_blks_hit tidx_blks_read heap表的索引对应的toast索引统计字段 tidx_blks_hit
希望能帮助到大家,还不理解就要打屁屁了。
2016 Postgres大象会官方报名通道:http://www.huodongxing.com/event/8352217821400
扫描报名
https://aihuishou.tiancebbs.cn/sh/3719.html https://www.tiancebbs.cn/ershoufang/468375.html https://aihuishou.tiancebbs.cn/sh/569.html https://xjxinjinqu.tiancebbs.cn/qths/455606.html https://su.tiancebbs.cn/hjzl/467139.html https://www.tiancebbs.cn/ershouwang/468664.html https://su.tiancebbs.cn/hjzl/469165.html https://sjz.tiancebbs.cn/b2bjxsb/56894.html https://zulin.tiancebbs.cn/sh/2332.html https://aihuishou.tiancebbs.cn/sh/2582.html https://sh.tiancebbs.cn/hjzl/459940.html https://zulin.tiancebbs.cn/sh/1073.html https://taicang.tiancebbs.cn/hjzl/461245.html https://www.tiancebbs.cn/ershouwang/468683.html https://weihai.tiancebbs.cn/qths/469041.html https://chuzhou.tiancebbs.cn/qths/463016.html https://aihuishou.tiancebbs.cn/store/2775/info-page-102.html
http://huilong.sctcbmw.cn/benxi/ https://ningwu.tiancebbs.cn/ http://yz.cqtcxxw.cn/jjbc/ http://fuyang.tjtcbmw.cn/bjyq/ http://huilong.sctcbmw.cn/ynxsbn/ http://js.sytcxxw.cn/cf/ http://huilong.sctcbmw.cn/sanming/ http://yz.cqtcxxw.cn/hbycd/ https://scdylj.tiancebbs.cn/ http://huaguang.jxtcbmw.cn/gansu/ https://xide.tiancebbs.cn/ http://yz.cqtcxxw.cn/yangpuqu/ http://ly.shtcxxw.cn/zhumadian/ http://xinguang.sctcbmw.cn/changningqu/ http://km.lstcxxw.cn/linzhi/ http://ly.shtcxxw.cn/shchangning/ https://zulin.tiancebbs.cn/ptsh/
关于美的作文:https://www.nanss.com/xuexi/2191.html 平安就好的说说:https://www.nanss.com/wenan/1974.html 关于四月的网名:https://www.nanss.com/mingcheng/2011.html 描写自己的作文:https://www.nanss.com/xuexi/2175.html 美团好评50字通用评论:https://www.nanss.com/shenghuo/2325.html 高级情侣cp昵称:https://www.nanss.com/mingcheng/1623.html 对付流言蜚语精辟句子:https://www.nanss.com/yulu/1638.html 餐饮人的心酸与不容易的句子:https://www.nanss.com/gongzuo/2204.html 詹天佑读后感:https://www.nanss.com/xuexi/2142.html 女人最好的状态的说说:https://www.nanss.com/wenan/2335.html 团委工作报告:https://www.nanss.com/gongzuo/2489.html 阳光正好微风不燥文案:https://www.nanss.com/wenan/1787.html 把某人恨之入骨的说说:https://www.nanss.com/wenan/1524.html 开启夜生活模式心情说说:https://www.nanss.com/wenan/2224.html 晨跑正能量满满的句子:https://www.nanss.com/yulu/1574.html 闺蜜愚人节玩笑:https://www.nanss.com/shenghuo/2390.html 闺蜜名字一御一甜:https://www.nanss.com/mingcheng/2322.html 悲惨世界读后感:https://www.nanss.com/xuexi/2132.html 秋天的树叶作文:https://www.nanss.com/xuexi/2239.html 网游名称:https://www.nanss.com/mingcheng/1823.html 梦幻名字符号:https://www.nanss.com/mingcheng/1804.html 八百字作文:https://www.nanss.com/xuexi/2088.html 我的动物朋友作文400字四年级下册:https://www.nanss.com/xuexi/2473.html 推荐一本好书500字作文:https://www.nanss.com/xuexi/2023.html 三八节讲话:https://www.nanss.com/gongzuo/2437.html 符号网名大全花样符号:https://www.nanss.com/mingcheng/2209.html 让人忍不住评论的文案:https://www.nanss.com/wenan/2463.html 家读后感:https://www.nanss.com/xuexi/2153.html 小妇人读后感:https://www.nanss.com/xuexi/2141.html 鲜花带来的好心情句子:https://www.nanss.com/yulu/1602.html