TiDB 和 MySQL 的索引实践

本文是我在比对 MySQL 和 TiDB 使用索引以及执行计划的一些总结,希望能够给大家带来帮助。


提前准备

上文 MySQL 的索引优化实践 中,我对 MySQL 的索引优化有了一定的概述,今天再针对 TiDB 的索引进行一些实战。

pt 表:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
CREATE TABLE `pt` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `data` longtext COMMENT '内容',
  `next_at` bigint(20) DEFAULT NULL COMMENT '下次时间',
  `update_at` int(11) NOT NULL COMMENT '更新时间',
  `created_at` int(11) NOT NULL COMMENT '创建时间',
  `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0未删除 1已删除',
  `invalid` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0正常 1作废',
  PRIMARY KEY (`id`),
  KEY `idx_next_at` (`next_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='pt表';

MySQL 和 TiDB 的 pt 表有 35 万行数据。

MySQL 的执行计划如下:

1
explain select * from pt where deleted=0 and invalid=0 and next_at<=15100004 ;

结果如图:

TiDB 的执行计划结果如图:

从上面的执行计划结果来看,两者的方式是不一样的。

至于到底是什么不一样呢?我猜想是因为他们对于索引的实现是完全不一样的,这个比较复杂,今天就不做阐述了,后面有时间再来探究吧。

MySQL 的索引优化实践

本文是我在使用 MySQL 过程中遇到的 SQL 查询导致的大量慢查询语句的索引优化实践总结,希望能够给大家带来帮助。


多数情况下,我们知道索引能够提高查询效率,但应该如何建立索引?索引的顺序如何?许多人却只知道大概。其实要理解这些概念并不难,而且索引的原理远没有想象的那么复杂。

提前准备

pt 表:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
CREATE TABLE `pt` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `data` longtext COMMENT '内容',
  `next_at` bigint(20) DEFAULT NULL COMMENT '下次时间',
  `update_at` int(11) NOT NULL COMMENT '更新时间',
  `created_at` int(11) NOT NULL COMMENT '创建时间',
  `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0未删除 1已删除',
  `invalid` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0正常 1作废',
  PRIMARY KEY (`id`),
  KEY `idx_next_at` (`next_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='pt表';

假如 pt 表有数据量 800 万,查询 SQL 语句及执行计划如下:

1
2
explain SELECT id FROM pt WHERE next_at <= 1514822400 AND deleted=0 AND invalid=0
1  SIMPLE  pt   NULL    ALL idx_next_at NULL    NULL    NULL    7843117 0.00    Using where

从上面的 SQL 执行计划可以很明显看出来是用到了索引,但是扫描的数据行有 784 万之多,基本上是全表扫描了,但是其实 SQL 语句本身的查询结果数据只有 3 万多行的。

解决Git fatal错误提示

本文是在 git push 数据时遇到的一个问题解决方法。


情景再现

错误信息:fatal: refusing to merge unrelated histories

我给大家还原一下以上错误,并且再来介绍一下如何解决并成功提交数据的。

  1. 你在本地新建一个项目jaeger-opentracing-examples
  2. 给这个项目添加一些数据;
  3. 执行 git add ., git commit -m "init"
  4. 在执行 git push origin master 之前,还需要执行git remote add origin https://github.com/yangwenmai/jaeger-opentracing-examples.git
  5. 执行 git pull origin master
  6. fatal: refusing to merge unrelated histories

这个问题,其实我以前也遇到过,但是以前是怎么解决的呢?

直接本地文件重命名,然后再从 GitHub 拉取项目,然后把本地项目的所有文件拷贝到拉取到的项目文件中,然后再提交数据并推上去。

这虽然是一种解决办法,也不无伤大雅,但是这个办法终归不是正统的解决之道,本着学习和专研的精神,不应该逃避问题的方式来达到解决问题,所以我 Google 了。

在MySQL PROCESSLIST中的 statistics 是什么?

本文是线上MySQL数据库问题的排查总结,希望能够对大家有所帮助。


statistics

线上服务出现大量的服务告警,怀疑是 MySQL 数据库的问题,查看监控发现有大量SQL慢查询,查询processlist,发现很多状态是 statistics。

processlist里面有好几个长时间处于 statistics 状态的线程,表示正在计算统计数据,以制定一个查询执行计划。 如果一个线程处于这种状态很长一段时间,可能是磁盘IO性能很差,或者磁盘在执行其他工作。

如何在MySQL里面执行表碎片优化?

本文给大家介绍当你的表有大量DELETE的时候,产生的表锁片如何清理,希望能够对大家有所帮助。


当我们在执行了 delete from table_name 之后会有大量的碎片空间占用,那我们应该怎么去释放呢?

如果你的 MySQL 存储引擎是 MyISAM ,那么直接执行 optimize table table_name;即可。

如果你的存储引擎是 InnoDB ,执行 optimize table table_name ,会有可能出现两行结果: 第一行: Table does not support optimize, doing recreate + analyze instead 第二行 OK

那到底有没有成功呢?其实是成功释放了表碎片空间的。

但是有提示 Table 不支持 optimize 怎么办呢?

其实对于 InnoDB 来说,要释放表锁片空间,我们可以采用 alter table table_name ENGINE=InnoDB

不管是 optimize 还是 alter table 都是会锁表的,我们在操作的时候要特别注意,要选择在表变更/使用的低峰期进行操作,否则会导致大量的锁表。

解释:ALTER table table_name 其实是一个空操作,类似于重建表,可以把旧的缓存以及表的碎片空间都释放掉。

虽然 optimize table table_name 也能够释放表锁片空间,但是我们还是建议使用 ALTER TABLE table_name ENGINE=InnoDB;

基于 Jaeger 的全链路追踪系统构建实战指南

本文我将带大家基于 Jaeger 构建全链路追踪系统,也包括一些我在这个过程中遇到的一些问题总结,希望能够对大家有所帮助。


Stargazers over time

Stargazers over time

分布式全链路跟踪系统是什么?

分布式链路跟踪的核心基本都是 Google Dapper 论文所述,使用全局 TraceID 表示一条调用链,连接各个服务调用(用 SPAN 表示),通过分析 SPAN 之间的父子关系形成跟踪树。 另外通过中间件的埋点和业务自定义的 Annotation ,记录日志并采用收集器进行离线和在线分析,从而实现调用链跟踪、优化决策等信息。

Dapper 是什么?

Dapper 是 Google 发表的分布式链路跟踪的论文。

Jaeger 是什么?

Jaeger 是 Uber 基于 Google Dapper 开发的分布式链路跟踪系统的实现。

其他

  • Ziplin

Golang 如何进行 cpu 和内存开销分析?

本文是我们在分析CPU和内存开销的过程中踩过的一些坑,还有一些经验总结,希望能够对大家有所帮助。


前言

作为DevOps,我们在日常搞的项目,从开发到测试然后上线,我们基本都局限在功能的单元测试,对一些性能上的细节很多人包括我自己,往往都选择视而不见, 后果往往让工具应用产生不可预测的灾难(it’s true)。有些人说底层的东西,或者代码层面的性能调优太深入了,性能提升可以用硬件来补,但我觉得这只是自欺欺人的想法,提升硬件配置这种土豪方法不能一直长存的,更何况 现在我们的工具哪个不是分布式的,哪个不是集群上跑的,为了冗余也好,为了易于横向扩展也罢,不可能保证所有的服务器都具备高性能的,我们不能让某些低配的服务器运行我们有性能缺陷的代码产生短板,成为瓶颈。 我记得2016年参与了一些通用服务agent的开发,由于要运行于公司全网几乎所有服务器中,生产上的环境复杂程度超乎我们想象。 一个问题到达很深入的时候,就已经是共同的问题 更何况Go语言已经为开发者内置配套了很多性能调优监控的好工具和方法,这大大提升了我们profile分析的效率,除了编码技巧,不断在实战项目中磨炼自己 对性能问题分析的能力,对日后我们在项目的把控力和一些功能布局都是很有帮助。

Golang的性能调优手段

Go语言内置的CPU和Heap profiler

Go强大之处是它已经在语言层面集成了profile采样工具,并且允许我们在程序的运行时使用它们, 使用Go的profiler我们能获取以下的样本信息: * CPU profiles * Heap profiles * block profile、traces等 Go语言常见的profiling使用场景

UDDB 入坑指南

本文是我们在使用 UDDB 的过程中的踩过的一些坑,以及一些经验总结,希望能够对大家有所帮助。


UDDB 概述

UDDB 是什么?

UDDB 的核心还是一个 MySQL 数据库中间件(类似 kingshard),只是产品本身是基于 UDB 的,而 UDDB 复用了 UDB 的强悍特性(安全、高可用、备份、监控、自动化运维等)。

UDDB 怎么用?

使用很简单的,只需要按照 UDDB 的产品文档上的 SQL 指南所述,然后用 upartition 语法创建好数据库表,就可以像使用普通表一样使用 UDDB 数据库了, UDDB 的容量是可水平扩展的。

注意:我们在使用的时候是有条件的:查询时, WHERE 子句里面需要带上分区的字段信息,不然查询就是扫描全部的子表了。

UDDB 有什么好处?

UDDB 只要在初始化时创建好表之后,只需要不断扩展这个表就好了,这样的好处非常多:

  • 一个是你可以根据数据量, 逐渐增加节点数。

比如一开始只需要存3个月的,可以只买3个节点,3个月后,等这3个节点写满,再购买3个新的节点,供后面3个月使用。而不需要一次性购买一年的节点。

  • 假如我们的数据只需要存6个月,那么可以把过期的子表给删除掉,然后腾出空间给后面月份的数据使用。

如何从 Github 同步你的 fork 仓库

本文是从 Github 同步你的fork 仓库的介绍。 Configuring a remote for a fork You must configure a remote that points to the upstream repository in Git to sync changes you make in a fork with the original repository. This also allows you to sync changes made in the original repository with the fork. Open Terminal. List the current