最新要闻
- 红豆哒 红豆泥日语(红豆泥日语)
- 问答平台 Reddit 上线帖子翻译功能,支持 8 种语言
- 迟延履行期债务利息的计算
- 美国对中国半导体的制裁,对美国有何影响?
- 8月外贸降幅收窄 逆势中培育新增长点
- 强化创新,打造跨境电商进口制度新高地
- 中土世界战争之影暗影之战无限守城(中土世界战争之影暗影战争阶段守城技巧分享)
- 已减弱为热带低压 中央气象台对台风“鸳鸯”停止编号
- 鼎际得POE高端新材料项目稳步推进 一期项目立项备案完成
- 问界M9率先用上!华为AR-HUD有多强:75寸画幅彻底干掉仪表盘
- 单日行程3300公里!博主称用18小时从黑龙江飙车至新疆引围观
- 7999元!华为Mate 60 Pro 1TB版本首次上架:今晚开抢
- 人人都离不开工具!PPT之父去世:塑造现代社会信息沟通方式
- 《名侦探柯南》漫画将迎来新篇章,白马探时隔十几年后再次登场?
- 中情局发布视频,要策反他们……
- 凯因科技:9月8日融资净买入306.7万元,连续3日累计净买入501.63万元
手机
2023年中国光学膜产业链上中下游市场分析(附产业链全景图)
周末不出城 也可赏苇打卡健身
- 2023年中国光学膜产业链上中下游市场分析(附产业链全景图)
- 周末不出城 也可赏苇打卡健身
- 山东聊城市东昌府区:行政审批 当天出证
- 降低二手房流通成本 澄迈首笔"带押过户"业务办结
- 深圳医保政策修订,10月1日起实施
- 推动金融服务向“够不够”升级,银行数字科技未来有五大趋势
家电
高性能MySQL实战(二):索引 | 京东物流技术团队
我们在上篇 高性能MySQL实战(一):表结构 中已经建立好了表结构,这篇我们则是针对已有的表结构和搜索条件为表创建索引。
(资料图片)
1. 根据搜索条件创建索引
我们还是先将表结构的初始化 SQL 拿过来:
CREATE TABLE `service_log` ( `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT "主键", `service_type` smallint NOT NULL DEFAULT -1 COMMENT "接口类型", `service_name` varchar(30) DEFAULT "" COMMENT "接口名称", `service_method` tinyint NOT NULL DEFAULT -1 COMMENT "接口方式 1-HTTP 2-TCP", `serial_no` int DEFAULT -1 COMMENT "消息序号", `service_caller` tinyint DEFAULT -1 COMMENT "调用方", `service_receiver` tinyint DEFAULT -1 COMMENT "接收方", `status` tinyint DEFAULT 10 COMMENT "状态 10-成功 20-异常", `error_message` varchar(200) DEFAULT "" COMMENT "异常信息", `message` varchinar(1000) DEFAULT "" COMMENT "报文内容", `create_user` varchar(50) DEFAULT "" COMMENT "创建者", `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT "创建时间", `update_user` varchar(50) DEFAULT "" COMMENT "更新者", `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT "更新时间", `is_delete` tinyint NOT NULL DEFAULT 0 COMMENT "刪除标志", `ts` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT "时间戳", PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT="接口调用日志";
现有如下搜索条件:
- 根据 接口名称来搜索对应的调用日志
- 根据 状态查询成功或异常的调用日志
- 根据 接口名称和 状态查询调用日志
- 根据 消息序号来获取一组调用日志
- 根据 创建时间的时间范围查询调用日志
- 根据 报文内容查询调用日志
索引是提升查询性能最有效的手段,它可以快速定位到记录,大大减少需要扫描的数据量,将随机 I/O 变为顺序 I/O,而且 B+ Tree 索引会根据索引值顺序存储,所以也能够应用于 排序和分组。
为了在查看这些接口调用日志时有更好的体验,那么我们就需要根据搜索条件来创建索引。
索引的类型尽量小
我们先关注下接口名称的搜索条件,我们可以发现:接口名称和接口类型这两个字段都能查询到相同类型接口的日志数据,只不过它们的类型不同,前者是字符串类型,后者是整型。
这时我们需要注意:选择创建索引的列的类型要尽量小。因为每创建一个索引就相当于创建了“一棵 B 树”,数据类型越小,那么索引占用的存储空间就越少,在一个数据页内就能存放更多的记录,因此磁盘 I/O 带来的性能损耗也就越少。
除此之外,在 MySQL 内部整型数据的比较相比于字符串类型的比较更简单,效率也更高。所以,我们会选择为接口类型创建索引而不是为接口名称创建索引。
为 接口类型列添加索引的 SQL 如下:
alter table service_log add index index_service_type(`service_type`);
根据条件 4,消息序号列也需要添加索引:
alter table service_log add index index_serial_no(`serial_no`);
冗余和重复索引
同样地,根据搜索条件 2,我们为状态列添加上索引:
alter table service_log add index index_status(`status`);
这时,我们再看看条件 3,需要为接口类型和状态添加 联合索引。不过需要注意的是:该联合索引和已经添加的接口类型索引是重复索引,根据联合索引的 最左匹配原则,第一列为接口类型的联合索引同样能为查询条件只有接口类型的查询服务,所以我们需要将原有为接口类型添加的索引删掉,再创建新的接口类型和状态的联合索引。
-- 删除 index_service_typealter table service_log drop index index_service_type;-- 添加联合索引alter table service_log add index index_service_type_status(`service_type`, `status`);
创建联合索引时有一个重要的经验性法则:将列值重复率最低的放到索引的最前列。如果重复的值过多,那么扫描到的数据行数也就越多,这样就会使得回表的压力很大。
通常情况下,把 WHERE 条件里面的列都独立地创建多个单列索引,在大部分情况下并不能提高MySQL的查询性能。我们应该尽可能的去考虑 索引列的顺序或者创建一个 全覆盖索引。
为重复率低的列创建索引
在我们的实际业务中,接口调用的状态几乎所有都是成功,很少会出现失败的情况,所以这时我们为状态列创建索引并不是很合适。因为如果我们查询所有状态为成功的数据,那么它可能会执行太多次的回表操作,导致查询效率下降,可能还不如执行全表扫描来的快。但是我们再考虑另一种情况,有时我们会根据状态为失败的记录做业务分析或排查问题,失败的数据是比较少的,如果我们通过索引查询就会非常高效,所以该列索引还有必要保留。
只不过我们在这里需要做一个处理:如果状态为成功时,我们为生成的 SQL 语句添加上忽略索引的关键字 ignore index(index_name),那么这样我们就能达到在查询成功状态的数据时全表扫描,而在查询失败状态的数据时使用索引了。
select * from service_log ignore index(index_status)where status = 10;
全值匹配和按值范围匹配的时间列
条件 5 根据创建时间来进行全值匹配和按值范围匹配非常适合创建索引:
alter table service_log add index index_create_time(`create_time`);
全文索引
FULLTEXT 全文索引是一种特殊类型的索引,它查找的是文本中的关键词,而不是直接比较索引中的值,更类似于搜索引擎所做的事情。在查询时适用于 MATCH AGAINST 操作,而不是普通的 WHERE 条件。
对于条件 5,我们需要在接口请求的报文中根据关键字,比如说包裹号来查询特定的数据,这就使得我们需要为报文内容列创建全文索引,SQL 如下:
alter table service_log add fulltext fulltext_message(`message`);-- 执行查询时的语句select * from service_log where match(message) against("123456");
全文索引在日常使用的并不多,它有许多需要注意的细节,如停用词、词干、复数和布尔搜索等,具体的详情信息可以查看文末的参考文献。
那么,最终初始化表结构的 DDL 语句如下:
CREATE TABLE `service_log` ( `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT "主键", `service_type` smallint NOT NULL DEFAULT -1 COMMENT "接口类型", `service_name` varchar(30) DEFAULT "" COMMENT "接口名称", `service_method` tinyint NOT NULL DEFAULT -1 COMMENT "接口方式 1-HTTP 2-TCP", `serial_no` int DEFAULT -1 COMMENT "消息序号", `service_caller` tinyint DEFAULT -1 COMMENT "调用方", `service_receiver` tinyint DEFAULT -1 COMMENT "接收方", `status` tinyint DEFAULT 10 COMMENT "状态 10-成功 20-异常", `error_message` varchar(200) DEFAULT "" COMMENT "异常信息", `message` varchar(1000) DEFAULT "" COMMENT "报文内容", `create_user` varchar(50) DEFAULT "" COMMENT "创建者", `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT "创建时间", `update_user` varchar(50) DEFAULT "" COMMENT "更新者", `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT "更新时间", `is_delete` tinyint NOT NULL DEFAULT 0 COMMENT "刪除标志", `ts` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT "时间戳", PRIMARY KEY (`id`), index index_serial_no(`serial_no`), index index_status(`status`), index index_create_time(`create_time`), index index_service_type_status(`service_type`, `status`), fulltext fulltext_message(`message`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT="接口调用日志";
前缀索引
一般情况下,对于 VARCHAR、BLOB 和 TEXT 等相关类型的列创建索引时,为了提升索引的性能和节省索引空间,会只对字段的前一部分字符进行索引,不过这样做的缺点是使得索引的选择性降低。
索引的选择性是指不重复的索引值和记录总数的比值,可以理解为重复率越低选择性越高,唯一索引的选择性为 1。
在我们的数据库表示例中,并没有字段适合建立前缀索引。其中报文内容列也并不适合创建前缀索引,因为这些报文的前缀都很相似,而且我们在执行查询时并不会带上前缀,而是只使用关键词信息查询。
但是,前缀索引比较重要,所以我们在这里也对创建前缀索引的方法介绍一下。
MySQL 并不支持对这些长字符类型列的完整内容进行索引,我们选择前缀长度的关键点在于:既要保证选择足够长的前缀使得选择性较高,同时又不能太长防止占用太多的空间。
可以根据如下方法来确定前缀的长度:
首先,查看要添加索引的列出现最频繁的一些值:
select count(0) as c, specific_columnfrom specific_tablegroup by specific_columnorder by c desclimit 10;
之后先从 3 个前缀字母开始匹配尝试:
select count(0) as c, left(specific_column, 3) as preffrom specific_tablegroup by preforder by c desclimit 10;
慢慢地增加前缀长度,直到这个前缀的选择性接近我们首次查询的完整列的选择性即可。
或者,采用如下的方法,先计算出完整列的选择性:
select count(distinct specific_column) / count(0)from specific_table;
然后分别计算不同前缀的选择性,直到找到与完整列接近的选择性前缀长度即可:
select count(distinct left(specific_column, 3)) / count(0) as sel3,count(distinct left(specific_column, 4)) / count(0) as sel4,count(distinct left(specific_column, 5)) / count(0) as sel5,count(distinct left(specific_column, 6)) / count(0) as sel6,count(distinct left(specific_column, 7)) / count(0) as sel7from specific_table;
不过,也有例外的情况,那就是即使现在我们选择了比较接近完整列选择性的前缀,但数据的分布仍然很不均匀。
这时我们需要用该前缀执行如下查询,并与完整列查询出的数目作比较,观察这些出现频率最高的前缀值与完整列出现频率是否接近,否的话需要再将前缀值调大。
select count(0) as c, left(specific_column, 5) as preffrom specific_tablegroup by preforder by c desclimit 10;-- 完整列的出现频率select count(0) as c, specific_columnfrom specific_tablegroup by specific_columnorder by c desclimit 10;
最后,找到合适的前缀数创建前缀索引可以使用如下 SQL:
alter table specific_table add index index_specific_column(specific_column(7));
虽然前缀索引能够使索引更小,更快,但是我们不能使用前缀索引做 ORDER BY 和 GROUP BY 操作,也无法使用前缀索引做索引覆盖。
2. 关于索引必须知道的事儿
下文中我们所说的索引如果没有特别指明类型,那么就代表我们说的是 B+ Tree 索引,它使用 B+ Tree 数据结构来保存数据。
B+ Tree 会将所有的数据保存在叶子节点上,并且通过双向链表将叶子节点连接起来。
聚簇索引
聚簇索引并不是一种单独的索引类型,而是一种数据存储方式,InnoDB 聚簇索引在数据页中同时保存索引和数据行,这使得它的数据访问相比于非聚簇索引(二级索引)要快。
聚簇的意思是说 数据行和相邻的键值紧凑的存储在一起,因为无法同时把数据行放在两个不同的地方,所以一个表只能有一个聚簇索引。InnoDB 根据 主键聚簇数据,如果没有定义主键,InnoDB 会自动生成一个唯一的隐式主键作为聚簇索引。
我们创建一个简单的表,并插入一些数据,来看一下 B+ Tree 索引的数据结构图:
create table demo ( c1 int, c2 int, c3 char(1), primary key(c1))engine=InnoDB;
MySQL 是通过 数据页来保存数据的,每个页的大小默认为 16KB,在每个数据页中都默认有最小记录 Infimum和最大记录 Supremum,如下图所示:
我们可以发现在叶子节点中保存了所有数据行,每个页之间通过页文件头部(File Header)记录的双向链表指针进行连接,数据记录之间通过单向链表连接,单向链表的指针记录在每行数据记录的 记录头信息中。
在非叶子节点中,我们可以发现记录的信息只有 主键值和对应的页号,因此数据页能存放的数据更多,B+ Tree 也就能更加 “矮胖”,这样就能使得磁盘 I/O 更少。一般情况下我们用到的 B+ Tree 不会超过 4 层。
B+ Tree 按照索引列数据的大小顺序排序存储,所以很适合按照范围来查询。每次搜索数据都从索引的根节点开始,通过比较节点中的值和要查找的值来找到合适的指针进入下层子节点,最终在叶子节点中找到或找不到对应的记录。
聚簇索引能够加快我们访问数据的速度,但是它也有一些局限性我们需要了解一下:
- 聚簇索引最大限度地提高了 I/O 密集型应用的性能,但如果 数据全部都放在内存中,则访问的顺序就没那么重要了,聚簇索引也就没什么优势了
- 随着 RAM 变得更便宜,而且许多数据集不是那么大,所以将它们全部保存在内存中是非常可行的,包括可能分布在多个服务器上,这也促进了内存数据库的发展。
- 插入速度严重依赖于插入顺序。按照主键的顺序插入行是将数据加载到 InnoDB 表中最快的方式。但如果不是按照主键的顺序插入,会因页分裂影响插入速度。最好避免随机的聚簇索引,特别是对于 I/O 密集型的应用
- 聚簇索引列更新的代价很高,因为它会强制 InnoDB 将每个被更新的行移动到新的位置,这也会发生页分裂,导致性能下降
二级索引
二级索引是非聚簇索引,InnoDB 引擎在 B+ Tree 的叶子节点存储的不是完成的数据记录,而只是 索引列和主键列的值。如果在查询时没有发生覆盖索引的话,需要根据主键值进行回表操作以获取需要的结果。
二级索引是关系型数据库的基础,并且在文档数据库中也很普遍。许多键值存储(如 HBase 和 Volde-mort)为了减少实现的复杂度而放弃了二级索引,但是一些(如 Riak)已经开始添加它们,因为它们对于数据模型实在是太有用了。并且次级索引也是 Solr 和 Elasticsearch 等搜索服务器的基石。
实际上,有两种用二级索引对文档数据库进行分区的方法:基于文档(document-based)的分区 和 基于关键词(term-based)的分区。
*基于文档的分区
假设我们有一个汽车销售网站,每条数据都有唯一的 ID,我们称之为文档 ID。我们使用文档 ID 进行分区,并为汽车颜色字段创建二级索引,分区结果如下图所示:
这样的二级索引分配方法,使得每个分区都是独立的:每个分区自己维护自己的索引,它不关心其他分区的数据,这种文档分区索引也被称为 本地索引。
当我们查询红色的汽车时,需要将请求发布到所有的分区,并合并所有返回的结果,这种查询数据库的方法被称为 分散/聚集,可能会使得二级索引查询数据比较耗时。
*基于关键词的分区
我们也可以构建一个覆盖所有分区数据的 全局索引,比如我们将 a 到 r 开头的颜色的二级索引保存在分区 0 中,将 s 到 z 的保存在分区 1 中,如下图所示:
我们将这种分区方法称为 关键词分区,根据关键词本身分区对于范围扫描非常有用,比如说我现在想获取 a 到 r 开头的颜色的所有汽车数据;而对关键词的哈希分区又能够提供分区负载均衡的能力。
基于关键词分区的全局索引优于文档分区索引的地方在于它的读取更加高效,并不需要将请求打到所有分区上,只需要将请求发送到含有对应关键词的分区即可,而它的缺点在于对单个分区文档的写入可能会产生多个分区的索引的数据变更,需要协调跨分区的分布式事务。
覆盖索引
覆盖索引可以简单地理解成 查询只需要访问索引列而无需访问其他数据列。
优秀的索引设计不单单只考虑 WHERE 条件,也会根据想要查询的列去综合分析。如果只需要索引列的话,那么覆盖索引是非常有用的工具,它能避免回表操作,这样 MySQL 就会极大地减少数据访问量,而且索引占用的空间很小,将这些数据缓存在内存中的压力远小于缓存所有相关数据行。
如果业务无需查询其他列,那么我们最好把业务需要的列放在查询列表中,以实现覆盖索引,而不是简单地以 * 来替代;在某些情况下,可以根据想要查询的列,对所使用的索引进行扩展,即增加想要查询的列达到覆盖索引的目的。
当执行一个覆盖索引的查询时,在 EXPLAIN 的 Extra 列可以看到 Using index 的信息。
自适应哈希索引
它是 InnoDB 的一个特性,当 InnoDB 发现某些索引值被非常频繁的访问时,它会在原有的 B+ Tree 索引之上,再在内存中构建一个哈希索引,以此来加快对应数据的访问。这个过程是自动化的,我们无法进行干预,不过可以通过参数配置将其关闭。
巨人的肩膀
- 《数据密集型应用系统设计》:第三章、第六章
- 《高性能 MySQL 第四版》:第七章
- 《MySQL 是怎样运行的》:第四、五、六、七章
- 14.6.2.4 InnoDB Full-Text Indexes
作者:京东物流 王奕龙
来源:京东云开发者社区 自猿其说Tech 转载请注明来源
关键词:
高性能MySQL实战(二):索引 | 京东物流技术团队
日本央行暗示将结束负利率 主要国家债券收益率走高
业绩说明会传递产品价值 国家电投REIT管理人解读多项收益增长点
浇灌“科技之花” 结出“产业之果”——科技成果转化一线观察
调查:美国个人消费或明年初收缩
内外盘标的资产波动不同 年内黄金ETF与黄金QDII基金份额增长率和收益率差异明显
国家统计局:8月份工业生产者出厂价格同比下降3.0% 环比上涨0.2%
安理会就乌克兰局势举行会议 中方呼吁:停火止战
LG MAGNIT 118 英寸 Micro LED 电视亮相,售价 237000 美元
国家统计局:8月份PPI同比下降3.0% 环比上涨0.2%
红豆哒 红豆泥日语(红豆泥日语)
2023年中国光学膜产业链上中下游市场分析(附产业链全景图)
北京丰台南苑一宗宅地挂牌 起始价近35亿元
麦咖啡不甘心当麦当劳的陪衬
信创产业营收业绩稳步增长迎布局机遇 信创指数ETF即将结束募集
河南省三门峡市卢氏县连翘产新收尾 行情暂无变化
周末不出城 也可赏苇打卡健身
2023年居民医保缴费标准提高至380元,是不是人人都只交380元呢?
最美开学季 快乐初体验——合肥市双岗幼儿园小班新生入园
男子钱包丢10年:被好心人分文不少送回
山东聊城市东昌府区:行政审批 当天出证
行业龙头资产突破4000亿!金融租赁“千亿俱乐部”增至14家 下半年有望再增员?
晶科能源姚臣谌:练好内功、超越ESG评价体系 推动行业绿色低碳转型
一顶帐篷撑起旅游新风口——解读新疆露营经济业态
山西700余种知名农特产品进入邮乐电商平台
摩洛哥皇家武装部队称该国地震造成约100人死亡
湖北南漳:“橘”下生“瓜” 套出村民致富路
知识水平趋近真人专家?蚂蚁财富发布大模型智能理财助理支小宝2.0
2023秋交会多重优惠吸引市民购房
国家统计局最新公布!8月CPI同比由降转涨,PPI同比跌3%
国家统计局:8月份居民消费价格同比上涨0.1% 环比上涨0.3%
问答平台 Reddit 上线帖子翻译功能,支持 8 种语言
降低二手房流通成本 澄迈首笔"带押过户"业务办结
深圳医保政策修订,10月1日起实施
珲春市公安局强势启动夏夜治安巡查宣防第三次集中统一行动
国家疾控局发布秋季儿童轮状病毒感染健康提示
统计局:8月CPI同比上涨0.1% 环比上涨0.3%
国光电气:9月8日融券卖出2.46万股,融资融券余额1.79亿元
人民币对土耳其里拉汇率是多少?9月8日土耳其里拉汇率实时查询
雅江县建设食用菌基地群众致富有渠道
20.88万元起 豪华智享超电SUV领克08正式上市
年内投用!天河机场T2航站楼商业以合资形式整体运营
股票可以继承吗
驾驶公司的车发生交通事故满足哪些条件是工伤
玩密室逃脱被吓摔骨折 法院判玩家自担部分风险
迟延履行期债务利息的计算
强降雨致珠三角多地发生内涝 广东全省提前转移8万余人
如何隐藏 Android 手机和平板电脑上的应用程序
推动金融服务向“够不够”升级,银行数字科技未来有五大趋势
厦门昼夜温差开始加大!市民需注意预防夜间着凉
信用卡逾期四个多月被起诉怎么办-信用卡逾期四个多月被起诉怎么办理
拿地1周后,中海胥江地块规划公示出炉!三大户型曝光
广州一学校食堂档口饭类售价低于13元被通知“罚款300元” 校方:已中止与管理公司承包协议
国少队出了一口恶气!日本队回家喝核污水 今晚国足+国奥双线出击
新老汽车品牌正在大浪淘沙,高管人事调整不可避免
育碧回应《AC黑旗》Steam停售:只是技术问题
腾讯发布智驾云图 副总裁钟翔平:将与车企共建汽车行业大模型
天原股份(002386.SZ):目前已经有包括头部企业在内的客户到公司验厂
第十一届环鄱赛开赛 30多个国家及港澳台地区选手参赛
干竹荪的家常做法窍门(干竹荪的家常做法)
守望初心 向卓修雅 温江区实验学校庆祝第39个教师节
茶叶生物碱(关于茶叶生物碱简述)
美国毛伊岛大火一个月 失联人员没人管 家属苦苦搜寻信息
192.168.1.1管理员默认密码是什么
智慧工地助力海南重点民生工程
非遗“西秦刺绣”造就锦绣产业丨高质量发展调研行
南宁市江南区推进违法卫片图斑整治 严守耕地红线
美国对中国半导体的制裁,对美国有何影响?
广发基金通信大使们的故事丨成为树洞和倾听者 为乡村孩子提供温暖陪伴
8月中国PPI同比下降3.0%
三测体温单
农行洛阳分行:政银合作为乡村振兴注入“源头活水”|乡村振兴 金融赋能
安徽六安:童心感师恩 祝福寄深情
报告显示AI人才需求旺盛,算法研究员最紧缺
8月外贸降幅收窄 逆势中培育新增长点
收获颇丰!第十五届湖南茶博会上安化茶产品斩获多项金奖
强化创新,打造跨境电商进口制度新高地
学好国家通用语言文字 拥抱更美好的未来
微软现已停售无线显示适配器 旧配件历史步入终结
2023年8月份居民消费价格同比上涨0.1% 环比上涨0.3%
1207名电信网络诈骗犯罪嫌疑人移交我方
辰安科技:中标珠海高新区应急管理局项目
香港交易所:今日证券及衍生产品市场延迟开市
开棋牌室很简单,一个字:"抄"。
阿莱德(301419):日K线呈现-“曙光初现”形态 后市看多(09-08)
江苏凯盛新材料公司年产150万吨光伏组件项目动工
香港特区政府:极端天气情况应对措施至少维持至今日24时
宝丰县在全省率先实施食品经营许可证市场主体消失代位注销
今年以来最强暴雨来袭!广州南沙全区停课一天,多处路段需绕行
中土世界战争之影暗影之战无限守城(中土世界战争之影暗影战争阶段守城技巧分享)
今日微信引流活动有哪些(微信引流营销王自动加好友好吗现在软件太多,不知道哪个好了)
今日湖南城市学院怎么样啊是几本(湖南城市学院怎么样啊)
12艘122亿元!淡水河谷将送给中国船厂一份大礼
山东郯城通报“一女子滥用职权威胁理发店”:对王某某给予记大过处分
这是难得的一餐,在大山中的柴火饭!记忆中的童年时光,这一切都是美好的!#农...
断联后如何知道对方是否还爱你?这些迹象可能是答案!
天津“跳水大爷”考验城市人文
张家口蔚县上好开学“法治第一课”
润贝航科:拟约1.8亿元投建先进航空复合材料研发中心及生产基地
大庆杜尔伯特腰新乡:“两癌”筛查护健康 党建引领促妇建