邢栋博客

邢栋博客,Action博客,记录工作和生活中的点点滴滴

redis底层数据结构总结
redis有五种对象的类型

REDIS_STRING  字符串对象
REDIS_LIST 列表对象
REDIS_HASH 哈希对象
REDIS_SET 集合对象
REDIS_ZSET 有序集合对象


底层数据结构共有八种
编码常量 编码对应的底层数据结构
1、REDIS_ENCODING_INT long类型的整数
2、REDIS_ENCODING_EMBSTR embstr编码的简单动态字符串
3、REDIS_ENCODING_RAW 简单动态字符串
4、REDIS_ENCODING_HT 字典
5、REDIS_ENCODING_LINKEDLIST 双端链表
6、REDIS_ENCODING_ZIPLIST 压缩列表
7、REDIS_ENCODING_INTSET 整数集合
8、REDIS_ENCODING_SKIPLIST 跳跃表和字典


1.字符串对象
编码可以为 int、embstr或者raw。
如果一个字符串的内容可以转换为long,那么该字符串就会被转换成为long类型,对象的ptr就会指向该long,并且对象类型也用int类型表示。
普通的字符串有两种,embstr和raw。embstr应该是Redis3.0新增的数据结构,在2.8中是没有的。如果字符串对象的长度小于39字节,就用embstr对象。否则用传统的raw对象。

2.列表对象
编码可以是ziplist或者linkedlist。
ziplist是一种压缩链表,它的好处是更能节省内存空间,因为它所存储的内容都是在连续的内存区域当中的。当列表对象元素不大,每个元素也不大的时候,就采用ziplist存储。但当数据量过大时就ziplist就不是那么好用了。因为为了保证他存储内容在内存中的连续性,插入的复杂度是O(N),即每次插入都会重新进行realloc。
linkedlist是一种双向链表。它的结构比较简单,节点中存放pre和next两个指针,还有节点相关的信息。当每增加一个node的时候,就需要重新malloc一块内存。

当列表对象可以同时满足以下两个条件时, 列表对象使用 ziplist 编码:
列表对象保存的所有字符串元素的长度都小于 64 字节;
列表对象保存的元素数量小于 512 个;
不能满足这两个条件的列表对象需要使用 linkedlist 编码。
ps:
因为压缩列表比双端链表更节约内存, 并且在元素数量较少时, 在内存中以连续块方式保存的压缩列表比起双端链表可以更快被载入到缓存中;
随着列表对象包含的元素越来越多, 使用压缩列表来保存元素的优势逐渐消失时, 对象就会将底层实现从压缩列表转向功能更强、也更适合保存大量元素的双端链表上面


3.哈希对象
编码可以是ziplist或者hashtable。
ziplist中的哈希对象是按照key1,value1,key2,value2这样的顺序存放来存储的。当对象数目不多且内容不大时,这种方式效率是很高的。
hashtable的是由dict这个结构来实现的,dict是一个字典,其中的指针dicht ht[2] 指向了两个哈希表。dicht[0]是用于真正存放数据,dicht[1]一般在哈希表元素过多进行rehash的时候用于中转数据。
dictht中的table用语真正存放元素了,每个key/value对用一个dictEntry表示,放在dictEntry数组中


4.集合对象
编码可以是intset或者hashtable。
intset是一个整数集合,里面存的为某种同一类型的整数,支持如下三种长度的整数:
#define INTSET_ENC_INT16 (sizeof(int16_t))  
#define INTSET_ENC_INT32 (sizeof(int32_t))  
#define INTSET_ENC_INT64 (sizeof(int64_t))  
intset是一个有序集合,查找元素的复杂度为O(logN),但插入时不一定为O(logN),因为有可能涉及到升级操作。比如当集合里全是int16_t型的整数,这时要插入一个int32_t,那么为了维持集合中数据类型的一致,那么所有的数据都会被转换成int32_t类型,涉及到内存的重新分配,这时插入的复杂度就为O(N)了。是intset不支持降级操作。

当集合对象可以同时满足以下两个条件时, 对象使用 intset 编码:
集合对象保存的所有元素都是整数值;
集合对象保存的元素数量不超过 512 个;
不能满足这两个条件的集合对象需要使用 hashtable 编码。
ps:
第二个条件的上限值是可以修改的, 具体请看配置文件中关于 set-max-intset-entries 选项的说明。


5.有序集合对象
有序集合的编码可能两种,一种是ziplist,另一种是skiplist与dict的结合。
ziplist作为集合和作为哈希对象是一样的,member和score顺序存放。按照score从小到大顺序排列。
skiplist是一种跳跃表,它实现了有序集合中的快速查找,在大多数情况下它的速度都可以和平衡树差不多。但它的实现比较简单,可以作为平衡树的替代品。
当有序集合对象可以同时满足以下两个条件时, 对象使用 ziplist 编码:
有序集合保存的元素数量小于 128 个;
有序集合保存的所有元素成员的长度都小于 64 字节;
不能满足以上两个条件的有序集合对象将使用 skiplist 编码。
ps:
以上两个条件的上限值是可以修改的, 具体请看配置文件中关于 zset-max-ziplist-entries 选项和 zset-max-ziplist-value 选项的说明。
mysql索引之聚簇索引和非聚簇索引

(一)各种树结构
1 搜索二叉树:每个节点有两个子节点,数据量的增大必然导致高度的快速增加,显然这个不适合作为大量数据存储的基础结构。

2 B树:一棵m阶B树是一棵平衡的m路搜索树。最重要的性质是每个非根节点所包含的关键字个数 j 满足:┌m/2┐ - 1 <= j <= m - 1;一个节点的子节点数量会比关键字个数多1,这样关键字就变成了子节点的分割标志。一般会在图示中把关键字画到子节点中间,非常形象,也容易和后面的B+树区分。由于数据同时存在于叶子节点和非叶子结点中,无法简单完成按顺序遍历B树中的关键字,必须用中序遍历的方法。

3 B+树:一棵m阶B树是一棵平衡的m路搜索树。最重要的性质是每个非根节点所包含的关键字个数 j 满足:┌m/2┐ - 1 <= j <= m;子树的个数最多可以与关键字一样多。非叶节点存储的是子树里最小的关键字。同时数据节点只存在于叶子节点中,且叶子节点间增加了横向的指针,这样顺序遍历所有数据将变得非常容易。

4 B*树:一棵m阶B树是一棵平衡的m路搜索树。最重要的两个性质是1每个非根节点所包含的关键字个数 j 满足:┌m2/3┐ - 1 <= j <= m;2非叶节点间添加了横向指针

B+树适合作为数据库的基础结构,完全是因为计算机的内存-机械硬盘两层存储结构。内存可以完成快速的随机访问(随机访问即给出任意一个地址,要求返回这个地址存储的数据)但是容量较小。而硬盘的随机访问要经过机械动作(1磁头移动 2盘片转动),访问效率比内存低几个数量级,但是硬盘容量较大。典型的数据库容量大大超过可用内存大小,这就决定了在B+树中检索一条数据很可能要借助几次磁盘IO操作来完成。



(二)存储引擎和索引
有两种常见的方法可以解决多个B+树访问同一套表数据的问题,一种叫做聚簇索引(clustered index ),一种叫做非聚簇索引(secondary index)。这两个名字虽然都叫做索引,但这并不是一种单独的索引类型,而是一种数据存储方式。对于聚簇索引存储来说,行数据和主键B+树存储在一起,辅助键B+树只存储辅助键和主键,主键和非主键B+树几乎是两种类型的树。对于非聚簇索引存储来说,主键B+树在叶子节点存储指向真正数据行的指针,而非主键。

InnoDB使用的是聚簇索引,将主键组织到一棵B+树中,而行数据就储存在叶子节点上,若使用"where id = 14"这样的条件查找主键,则按照B+树的检索算法即可查找到对应的叶节点,之后获得行数据。若对Name列进行条件搜索,则需要两个步骤:第一步在辅助索引B+树中检索Name,到达其叶子节点获取对应的主键。第二步使用主键在主索引B+树种再执行一次B+树检索操作,最终到达叶子节点即可获取整行数据。

MyISM使用的是非聚簇索引,非聚簇索引的两棵B+树看上去没什么不同,节点的结构完全一致只是存储的内容不同而已,主键索引B+树的节点存储了主键,辅助键索引B+树存储了辅助键。表数据存储在独立的地方,这两颗B+树的叶子节点都使用一个地址指向真正的表数据,对于表数据来说,这两个键没有任何差别。由于索引树是独立的,通过辅助键检索无需访问主键的索引树。


(三)聚簇索引的优势
1 由于行数据和叶子节点存储在一起,这样主键和行数据是一起被载入内存的,找到叶子节点就可以立刻将行数据返回了,如果按照主键Id来组织数据,获得数据更快。

2 辅助索引使用主键作为"指针" 而不是使用地址值作为指针的好处是,减少了当出现行移动或者数据页分裂时辅助索引的维护工作,使用主键值当作指针会让辅助索引占用更多的空间,换来的好处是InnoDB在移动行时无须更新辅助索引中的这个"指针"。也就是说行的位置(实现中通过16K的Page来定位,后面会涉及)会随着数据库里数据的修改而发生变化(前面的B+树节点分裂以及Page的分裂),使用聚簇索引就可以保证不管这个主键B+树的节点如何变化,辅助索引树都不受影响。


原文地址:http://www.admin10000.com/document/5372.html


回顾mongo索引

测试索引

新建50万条数据
for(var i=0;i<500000;i++){db.myusers.insert({"i":i,"username":"user"+i,"age":Math.floor(Math.random()*120),"created":new Date()});}
db.myusers.find({username:"user111"}).explain(true)
{
............
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 1,
"executionTimeMillis" : 238,//-------------
"totalKeysExamined" : 0,
"totalDocsExamined" : 500000,//-------------
"executionStages" : {
"stage" : "COLLSCAN",//-------------
"filter" : {
"username" : {
"$eq" : "user111"
},
..............
}

增加索引
db.myusers.createIndex({"username":1})
好处:提高查询效率
坏处:数据增删改时会变慢
限制:每个集合最多64个索引
db.myusers.find({username:"user111"}).explain(true)
{
.................
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 1,
"executionTimeMillis" : 0, //-------------
"totalKeysExamined" : 1,
"totalDocsExamined" : 1,//-------------
"executionStages" : {
"stage" : "FETCH",//-------------
"nReturned" : 1,
"executionTimeMillisEstimate" : 0,
..................
}


复合索引
索引--{"age":1,"username":1}
db.myusers.find({"age":21}) 高效
db.myusers.find({"age":21}).sort({"username":-1})高效
db.myusers.find({"age":{"$gte":21,"$lte":30}})高效
db.myusers.find({"age":{"$gte":21,"$lte":30}}).sort({"username":-1})一般


特殊索引
创建一个固定集合,最大1000字节,最多100个文档,超过后会自动删除最老的文档
db.createCollection('my_collection',{'capped':true,'size':1000,'max':'100'})

TTL索引
在lastUpdated字段建立TTL索引,当服务器时间比该字段存储的日期类型时间晚86400秒之后,文档立即删除。
Mongodb每分钟对ttl索引执行一次清理
db.my_collection.createIndex({"lastUpdated":1},{"expireAfterSecs":86400})


地理空间索引
2dsphere,用于球体表面,使用GeoJSON格式(geojson.org)

{'name':'Sjm','loc':{'type':'Point','coordinates':[116.34,40.02]}}
线
{'name':'River','loc':{'type':'Line','coordinates':[[0,1],[0,2],[1,2]]}}

{'name':'Beijing','loc':{'type':'Polygon','coordinates':[[2,1],[2,2],[4,2]]}}

创建索引
db.world.createIndex({'loc':'2dsphere'})
查询
var littleVillage={
'type':'Polygon',
'coordinates':[[-70,30],[-71,40],[-70,38],[-71,40]]
}
与littleVillage有交集的区域的文档:
db.world.find({'loc':{'$geoIntersects':{'$geometry':littleVillage}}})
完全包含在littleVillage区域的文档
db.world.find({'loc':{'$within':{'$geometry':littleVillage}}})
littleVillage区域附近的文档

db.world.find({'loc':{'$near':{'$geometry':littleVillage}}})


mongodb复制集学习笔记
conf.conf 如下

bind_ip=192.168.1.100
 port = 28001

 logpath=/usr/local/mongodb/logs/28001
 logappend=true
 dbpath=/usr/local/mongodb/datas/28001
 replSet=imooc

 fork = true

查看当前复制集状态
rs.status()
或者
use admin;
db.adminCommand({replSetGetStatus:1})

查看当前复制集配置文件
rs.conf()

show log rs  #查看当前mongodb的日志

rs.stepDown(50) ## 把当前主节点50秒内降级为从节点

rs.isMaster()  # 查看节点信息

/usr/local/mongodb/bin/mongo 10.51.105.19:28001/admin
//建立配置
config={_id:"imooc",members:[{_id:0,host:"10.51.105.19:28001"}, {_id:1,host:"10.51.105.19:28002"},{_id:2,host:"10.51.105.19:28003"}]}
//配置仲裁节点
config.members[2]={"_id":2,"host":"10.51.105.19:28003","arbiterOnly":true}
//使配置文件生效,初始化
rs.initiate(config)  ### rs.reconfig(config) 重新加载配置文件

测试同步
主节点上
use study
imooc:PRIMARY> db.test.insert({"name":"xd"})
子节点上
imooc:SECONDARY> rs.slaveOk(1)
imooc:SECONDARY> use study
imooc:SECONDARY> db.test.find()

复制集配置文件参数

_id: 整数0
host:字符串 “127.0.0.1:27017“
arbiterOnly: 布尔值 true
priority:整数 0|1   该节点的优先级,如果设置为0,则永远不会升级为主节点
hidden:布尔值 true|false 或者 1|0 ,如果设置为false, 优先级 要设置为0,隐藏节点
votes:整数  0|1  具有投票
slaveDelay 整数 slaveDelay 3600  延迟节点 延迟多少秒进行复制
buildIndexes 布尔值  true|false 或者 1|0  主节点建立索引,子节点是否同步,如果设为false, 优先级 应设置为0

关于oplog
Oplog大小及意义
默认大小
     64位操作系统linux,windows为当前分区可用空间的5%,体积不会超过50G

imooc:PRIMARY> use local
imooc:PRIMARY> db.oplog.rs.status()
imooc:PRIMARY> db.oplog.rs.find().sort({$natural:-1}).limit(1).pretty()  //查看最近的一条数据,pretty()格式化输出

单节点启动复制后,如果要增加机器
rs.add({_id:1,host:" 10.51.105.19:28002"})

调整oplog大小
imooc:PRIMARY>rs.freeze(100)
imooc:PRIMARY>rs.stepDown(100)
然后退出kill掉这个进程,注释掉配置文件的  replSet=imooc,重新启动

>use local
>show table ## 可以看到    oplog.rs
> db.oplog.rs.find().sort({$natural:-1}).limit(1)
>db.temp.save( db.oplog.rs.find().sort({$natural:-1}).limit(1).next())
>db.oplog.rs.drop()
>db.createCollection("oplog.rs",{capped:true,size:1024 * 1024 * 1024 * 3})
>db.oplog.rs.save(db.temp.findOne())

步骤总结
1.将成员以单机模式启动
2.将oplog最新的一条记录保存到临时表中   db.temp.save( db.oplog.rs.find().sort({$natural:-1}).limit(1).next())

3.删除原来的oplog.rs集合
4.以创建封顶表的形式创建oplog.rs , db.createCollection("oplog.rs",{capped:true,size:1024 * 1024 * 1024 * 3})

5.将之前保存的原oplog中的最新操作插入到新的oplog.rs集合中   db.oplog.rs.save(db.temp.findOne())

6.将单节点模式的节点返回到复制集中

复制集状态查看
rs.status()  复制集状态查询
rs.printReplicationInfo() 查看oplog状态
rs.printSlaveReplicationInfo() 查看复制延迟
db.serverStatus() 查看状态详情

mongodb 监控工具
1.mongostat
     mongostat 常用选项
          --host      主机名,或者 主机名:端口

          --port     端口
         --username 用户(验证)
          --password 密码(验证)
          --authenticationDatabase 从哪个数据库进行验证
          --discover 发现集群其他节点
     重点关注字段
     getmore 大量的排序操作在进行
     faults 需要的数据不在内存中
     locked db 锁比例最高的库
     index miss 索引未命中
     qr|qw读写产生队列,供求失衡
2.mongotop 监控当前集合读写统计信息
           --host     主机名,或者 主机名:端口
          --port     端口
         --username 用户(验证)
          --password 密码(验证)
          --authenticationDatabase 从哪个数据库进行验证

安全篇
     开启认证
          auth 单点  auth=true
          keyfile  集群之前认证

    集群认证

          keyfile文件的生成(内容base64编码集[a-zA-Z+/],长度1000字节,权限chmod 600 keyFile)
          openssl rand -base64 102  > .keyFile
          调整权限
          chmod 600  .keyFile
          开启认证需要在配置文件中增加
          setParameter=enableLocalhostAuthBypass=1  ## 本地例外,mongo localhost:28001
           keyFile=/usr/local/mongodb/.keyFile


     创建用户(创建第一个用户role要为root,db为admin)
          db.createUser(
          {
               user:'action',#字符串
               pwd:'123',#字符串
               roles:[{role:'root',db:'admin'}] #数组+对象,
          })
          创建用户后,然后登录客户端
          use admin
          db.auth('admin','123')

      删除用户
          db.dropUser(<username>)  ###删除某个用户
          db.dropAllUsers() ###删除当前库的所有用户

     权限
          built-in roles
                 读写
                    read  readWrite
                  管理员
                    dbAdmin dbOwner userAdmin  clusterAdmin clusterManager clusterMonitor hostManager
                  备份
                    backup  restore
                   全局
                    readAnyDatabase readWriteAnyDatabase userAdminAnyDatabase dbAdminAnyDatabase
                    超级用户
                    root
             自定义角色
                   use admin
                    db.createRole(
                    {
                         role:<role_name>,
                         privileges:[
                             {resource:{db:<db_name>,collection:<coll_name>},actions:[<action_name>]}
                         ],
                         roles:[{role:<role_name>,db:<db_name>}]
                    })

                    db.runCommand({userInfo:'admin',showPrivileges:1})  ##查看权限详情


          修改用户名密码
          需要具备 changePassword changeOwnPassword
          db.changeUserPassword(<user_name>,<new_password>)
          db.updateUser(<user_name>,{update_object})

          权限伸缩
               如何增加权限
               db.grantRolesToUser(
                    <user_name>,
                    [{role:<role_name>,db:<db_name>}]
               )
               如何收缩权限
               db.revokeRolesFromUser(
                    <user_name>,
                    [{role:<role_name>,db:<db_name>}]
               )
mysql表字段Note

物理设计
数据类型的选择
如何选择 VARCHAR和CHAR类型
1.使用最小的符合需求的长度
2.varchar(5) varchar(200) 存储mysql字符串性能不同

varchar的适用场景
1.字符串列的最大长度比平均长度大很多
2.字符串列很少被更新
3.使用了多字节字符集存储字符串

char类型的存储特点
1.char类型是定长的
2.字符串存储在char类型的列中会删除末尾的空格
3.char类型的最大宽度为255

char的适用场景
1.char类型适合存储长度近似的值
2.char类型适合存储短字符串
3.char类型适合存储经常更新的字符串列



如何存储日期数据
DATATIME 类型 占用8个字节的存储空间  字段名+datatime(6) 微秒
TIMESTAMP类型 占用4个字节 依赖于所指定的时区 ,在行的数据修改时可以自动修改timestamp列的值 字段名+timestamp(6) 微秒

date类型和time类型
date类型特点 
1.使用date类型只需要占用3个字节
2.使用date类型还可以利用日期时间函数进行日期之间的计算

time类型特点 ,用于存储时间数据,格式为HH:MM:SS


mysqlSQL优化Note

慢查询日志介绍

slow_query_log  //启动停止记录慢查询日志   show variables like 'slow_query_log';  set global slow_query_log = on;

slow_query_log_file  指定慢查询日志的存储路径及文件

long_query_time 指定记录慢查日志sql执行时间的阀值 // show variables like 'long_query_time';

log_queries_not_using_indexes 是否记录未使用索引的sql


常用的慢查询分析工具(mysqldumpslow)
mysqldumpslow -s r -t 10 slow_mysql.log
-s order (c,t,l,at,al,ar) {c:总次数 t:总时间 l:锁的时间 r:总数据行 at,al,ar平均数 at=总时间/总次数}
-t top 指定前几条作为结束输出

常用的慢查询分析工具pt-query-digest
pt-query-digest --explain h=127.0.0.1,u=root,p=p@1314 slow_mysql.log

实时获取有性能问题的SQL
select ID,USER,HOST,DB,COMMAND,TIME,STATE,INFO from information_schema.PROCESSLIST where TIME > 3;




mysql服务器处理查询请求的整个过程
1.客户端发送sql请求给服务器
2.服务器检查是否可以在查询缓存中命中该sql
3.服务器端进行sql解析,预处理,再由优化器生成对应的执行计划
4.根据执行计划,调用存储引擎api来查询数据
5.将结果返回给客户端

查询缓存对sql性能的影响
query_cache_type 设置查询缓存是否可用 ||demand 表示只有在查询语句中使用sql_cache和sql_no_cache来控制是否需要缓存on 开启off 关闭
query_cahce_size 设置查询缓存的内存大小
query_cache_limit 设置查询缓存可用存储的最大值 
query_cache_wlock_invalidate 设置数据表被锁后是否返回缓存中的数据
query_cache_min_res_unit 设置查询缓存分配的内存块最小单位



确定查询处理各个阶段所消耗的时间
1.使用profile
set profiling = 1;
执行查询
show profiles;
show profile for query N; //查询每个阶段所消耗的时间
show profile cpu for query 1;

2.使用performance_schema
update setup_instruments set enabled='YES' where name like 'stage%';
update setup_consumers set enabled='YES' where name like 'events%';


如何修改大表的表结构
pt-online-schema-change \
--alter="MODIFY c VARCHAR(150) NOT NULL DEFAULT ''" \
--user=root --password=1314 D=databasename,t=tablename \
--charset=utf8 --exexute


mysql索引优化Note

Mysql支持的索引类型

B-tree索引
    特点
        B-tree索引以B+树的结构存储数据
        B-tree索引能加快数据的查询速度
        B-tree索引更适合进行范围查找[顺序存储]
    在什么情况下可以用到B数索引
        1.全值匹配的查询
            order_sn = '123456'
        2.匹配最左前缀的查询
        3.匹配列前缀查询
            order_sn like '123%'
        4.匹配范围值的查找
            order_sn > '123456' and order_sn < '654321'
        5.精确匹配左前列并范围匹配另外一列

        6.只访问索引的查询

    Btree索引的使用限制

        1.如果不是按照索引最左列开始查找,则无法使用索引
        2.使用索引时不能跳过索引中的列
        3.Not in 和 <> 操作无法使用索引
        4.如果查询中有某个列的范围查询,则其右边所有列都无法使用索引

Hash索引
    Hash索引是基于hash表实现的,只有查询条件精确匹配hash索引中所有列时,才能够使用到hash索引;
    对于Hash索引中的所有列,存储引擎都会为每一行计算一个hash码,hash索引中存储的就是hash码。

    Hash索引的限制
        1.Hash索引必须进行二次查找
        2.Hash索引无法用于排序
        3.Hash索引不支持部分索引查找也不支持范围查找
        4.Hash索引中的hash码的计算可能存在hash冲突


为什么要使用索引
    1.索引大大减少了存储引擎需要扫描的数据量
    2.索引可以帮助我们进行排序可以避免使用临时表
    3.索引可以把随机I/O变为顺序I/O

索引的缺点
    1.索引会增加写操作的成本
    2.太多的索引会增加查询优化器的选择时间


索引优化策略
    1.索引列上不能使用表达式或函数
    2.前缀索引和索引列的选择性
        create index index_name on table(col_name(n));
    索引的选择性是不重复的索引值和表的记录数的比值

3.联合索引
    如何选择索引列的顺序
        经常会被使用到的列优先
        选择性高的列优先
        宽度小的列优先

4.覆盖索引
    优点
        1.可以优化缓存,减少磁盘I/O操作
        2.可以减少随机I/O,变随机IO操作为顺序IO操作
        3.可以避免对Innodb主键索引的二次查询
        4.可以避免MyISAM表进行系统调用
    无法使用覆盖索引的情况
        1.存储引擎不支持覆盖索引
        2.查询中使用了太多的列
        3.使用了双%号的like查询

使用索引来优化查询
    使用索引扫描来优化排序
        1.索引的顺序和order by子句的顺序完全一致
        2.索引中所有列的方向(升序、降序)和order by子句完全一致
        3.order by 中的字段全部在关联表中的第一张表中
模拟hash索引优化查询
        1.只能处理键值的全职匹配查询
        2.所使用的hash函数决定着索引建的大小

利用索引优化锁
    1.索引可以减少锁定的行数
    2.索引可以加快处理速度,同时也加快了锁的是释放
        例子:
        begin;
        select * from test where name = 'x' for update;
        ----
        在开一个事务
        begin;
        select * from test where name = 'y' for update;
        如果name 没有索引,第二个事务将卡住,否则将顺利执行

删除重复和冗余的索引
    pt-duplicate-key-checker h = 127.0.0.1

查询未被使用过的索引
    select object_schema,object_name,index_name,b.`TABLE_ROWS` from performance_schema.table_io_waits_summary_by_index_usage a join information_schema.TABLES b on a.`OBJECT_SCHEMA`=b.`TABLE_SCHEMA` AND a.`OBJECT_NAME` = b.`TABLE_NAME` where index_name is not null and count_star = 0 order by object_schema,object_name;

更新索引统计信息及减少索引碎片
    analyze table table_name;
    optimize table table_name; //使用不当会导致锁表


关于mysql的基准测试之mysqlslap和sysbench

mysql基准测试工作之 - mysqlslap

常用参数说明
--atuo-generate-sql 由系统自动生成sql脚本进行测试
--auto-generate-sql-add-autoincrement 在生成的表中增加自增ID
--auto-generate-sql-load-type 指定测试中使用的查询类型
--auto-generate-sql-write-number 指定初始化数据时生成的数据量
--concurrency 指定并发线程的数量
--engine指定要测试表的存储引擎,可以用逗号分割多个存储引擎
--no-drop 指定不清理测试数据
--iterations 指定测试运行的次数
--number-of-queries 指定每一个线程执行的查询数量
--debug-info 指定输出额外的内存以及cpu统计信息

--number-int-cols 指定测试表中包含的INT类型列的数量
--number-char-cols 指定测试表中包含的varchar类型列的数量

--create-schema 指定了用于执行测试的数据库的名字
--query 用于指定自定义SQL的脚本
--only-print 并不运行测试脚本,而是把生成的脚本打印出来


mysql基准测试工作之 - sysbench

安装说明
https://github.com/akopytov/sysbench/archive/0.5.zip
unzip sysbench-0.5.zip
./autogen.sh
./configue --with-mysql-includes=/usr/local/mysql/include/ --with-mysql-libs=/usr/local/mysql/lib/
make && make install
常用参数说明
--test 用于指定所要执行的测试类型,支持以下测试
Fileio 文件系统I/O性能测试
cpu cpu性能测试
memory 内存性能测试
oltp 测试要指定具体的lua脚本 //lua脚本位于sysbench-0.5/sysbench/tests/db
--mysqldb 用于指定执行基准测试的数据库名字
--mysql-table-engine 用于指定所使用的的存储引擎
--oltp-tables-count 执行测试的表的数量
--oltp-tables-size 执行每个表中的数据行数
--num-threads 指定测试的并发线程数量
--max-time 指定最大的测试时间
--report-interval 指定间隔多长时间输出一次统计信息

--mysql-user 指定执行测试的mysql用户
--mysql-password 指定执行测试的mysql用户的密码

prepare 用于准备测试数据
run 用于实际进行测试
cleanup 用于清理测试数据



优惠券
最新微语