Files
Hui-s-notebook/logseq-java/journals/2022_09_13.md
2024-02-02 00:12:49 +08:00

7.7 KiB
Raw Blame History

  • 索引的概念
    • 用于提高查找速度的一种数据结构
  • 为什么要用B+树B-树和B+树区别,为什么不用红黑树
    • Hash表结构存储数据
      • 通过key的hash计算得到存储下表
      • Hash只能进行等值查询切换速度非常快但是无法用于范围查询
    • 二叉查找树
      • 左边小,右边大,自身带排序
      • 二分查找
      • 极端情况
        • 根节点的选取,如果选取不好就会不平衡
        • 出现某一个方向子树过长
    • 平衡二叉树
      • 改善二叉树极端情况
      • 降低IO次数每走一个节点进行一次IO
      • 数的高度过高IO性能下降
    • B树
      • 存放指针及数据,保存了排序功能
      • 指定阶数M一个节点包含的子节点最大数量M越大高度越低
      • 范围查询大的时候需要返回根节点再次便利
      • 存储了data信息记录增多的时候树的高度会变高
    • B+树
      • 数据全部存在子节点中,非子节点只存储键值和指针
      • 子节点之间添加链表结构,解决范围查询时需要返回根节点
      • 范围查询效率提高很多单个查询比B+树提高不大
  • 那些情况适合建立索引,那些不适合建立索引
    • 频繁使用where
    • 分组字段,分组的前提为排序
    • 统计字段
      • 加了索引不需要产生中间表去重
    • 频繁更新字段
    • 数据单一固定
    • 数据量大(数据类型text)
    • where条件不怎么用的
  • 索引分类,最左前缀,聚簇索引
    • 主键索引
    • 唯一索引(一级索引)
    • 普通索引(二级索引)
    • 联合索引(需要符合最左前缀原则)
    • 最左前缀
      • 第一个值为从小到大排序,第二个不是
      • 第一个值确定的情况下,第二个值是有序的
      • 从最左边开始连续的索引都可以匹配上,直到遇到范围查询,> < between
      • 已经排序好的字段是会生效的,
        • a=1 and b>1 ab都会生效
        • a>1 and b=1 b索引会失效a>1 时b为无序的
    • MyISAM和InnoDB数据结构
      • MYD数据 MYI索引
      • ibd数据和索引读一个文件速度更快
    • 聚簇索引
      • 根据主键索引可以直接拿到数据,索引和数据放在一起
      • InnoDB
        • 定义主键为聚簇索引
        • 未定义索引选择第一个部位null唯一索引
        • 以上都没用使用一个6字节长整型的隐式字段ROWID字段构建聚簇索引该RPWID字段会在插入新行时自动递增
    • 非聚簇索引(辅助索引)
      • 除聚簇索引外
      • 只存储主键ID
      • 查询可能需要回表通过辅助索引查询得到ID去主键索引中查找
      • MyISAM中通过主键查询得到数据在硬盘中的地址再根据该地址去磁盘中寻找
      • 主键索引唯一,辅助索引可能等值也会查询出多个数据
    • 索引覆盖
      • 通过辅助索引可以获得全部数据,不需要回表
    • 索引失效
      • select *
      • %左边
      • 未最左匹配
      • 数据库认为不要
      • 计算
      • or
      • = > <
    • 优化
      • 辅助索引覆盖
      • 自增主键ID
      • 避免select *
      • 少用子查询,能使用外连接就外连接,避免笛卡尔积
      • 使用短索引,非叶子节点存储更多索引降低树的高度
    • 为什么推荐使用自增主键作为索引
      • 页分裂
      • 降低复杂度
  • List集合
    • 结合源码,回答核心流程,夹带关键字
    • ArrayList
      • 如何扩容,大小如何自动增加
          1. 初始化,未给定长度,默认调用午餐构造器
          • elementdata 常量数组为空
          • new之后数组长度为0
          1. 添加第一个元素
          • 计算容量比较长度后返回初始化长度为10
          1. 数组扩容
          • grow方法增加长度
          • 新容量为老容量加上老容量右移以为即1.5倍
          • 掉用复制数组的方法
    • 复制某个ArrayList到另一个里面去
      • clongaddAllcopystream流
      • 重写Clone方法
      • 浅复制
        • 返回一个一样的ArrayList其中一个改变了元素另一个也会改变
        • 两个集合中存储同一份元素引用
      • 深复制
        • 重写clone方法使用迭代器便利重新创建引用对象逐个添加
    • 索引中ArrayList增加或删除某个元素的运行过程效率很低吗
      • 效率很低添加或删除某个元素都需要对数组中的元素进行移位需要不断进行ArrayCopy很浪费时间
      • 添加,后面元素都后移一位,再添加
      • 删除,后面元素都前移一位覆盖
    • 很大的数组需要拷贝,如何快速拷贝
      • 创建时就指定数组的大小
    • 获得线程安全的ArrayList
      • synchorizoned关键字
    • LinkedList和ArrayList如何选择
      • ArrayList底层为数组查询效率高增删效率低
      • LinkedList底层为链表查询效率低增删效率高
    • Vector
      • 扩容为2倍线程安全
  • Set
    • HashSet
      • 无序,去重,非线程安全
      • new新建HashMap
      • 底层通过HashMap的key值实现的值为常量PRESENT(一个空的Object对象)
        • put调用setValue方法
      • 添加时为什么要给个value为PRESENT常量
        • PRESENT决定返回oldValue还是null判断是否已经存在
      • HashSet remove方法比较PRESENT
        • HashMap的删除方法成功会返回value失败返回null通过返回判断是否删除
      • 去重原理
        • hashcode和equals方法
        • 先判断hash值再通过==和wquals判断返回true则为重复元素
      • HashSet和TreeSet
        • 无序HashSet有序TreeSet
      • 如何得到一个线程安全的Set集合
        • Collections.synchorizeonedSet()
  • HashMap的底层结构
    • jdk1.7 数组+单向链表
    • jdk1.8 数组+链表(单向/双向)+红黑树
    • 内部定义静态Node类
      • Node<K, V>
      • TreeNode有TreeNode leftTreeNode right继承LinkedHashMap.Entry继承HashMap.Node
    • 如何解决Hash碰撞
      • 存放元素需要通过Hash计算来得到Hash值Hash值为元素要存放的位置当两个不同元素经过Hash计算得到的Hash值相同两个元素要存放在同一个位置产生冲突
      • HashMap的put方法
        • 初始化table数组长度为16第一次添加table为null通过resize()方法,给新容量16阈值16*0.75
        • threadhold扩容因子0.75
    • 何时从单链表转化为红黑树
      • 常量TREEIFY_THREADHOLD = 8 通过treeify()方法重组为红黑二叉树
    • 扩容方法
      • 通过resize方法扩容判断是否达到阈值达到就扩容为原来的两倍
      • 数组长度小于临界值MIN_TREEIFY_64或等于null时
    • 何时扩容
      • 转红黑树时要判断,转换时需要搬运元素,第一个元素要扩容
      • 添加一个元素后
    • HashMap设置长度为11那么数组容量为多少
      • tbaleSizeFor()方法重组
      • hash计算更加平均与数组长度值有关
      • 设置为大于我们自定义的值的第一个2的幂次方的值设置为11长度为16
    • HashMap何时从红黑树转化为单链表模式
      • 扩容时需要搬运数据,如果红黑二叉树不需要转化条件就会转化为链表
      • resize()方法转移红黑二叉树时会调用splite()方法
      • loheadhihead分割时会产生高位树和低位树小于等于6时调用untreeify方法退回链表结构
    • 多线程并发使用时,容易造成死循环/死锁
      • 非线程安全
      • jdk1.7头插法jdk1.8尾插法
    • ConcurrentHashMap
      • 线程安全的集合
      • ConcurrentHashMap在jdk1.7和1.8的区别
        • jdk1.7 Segment段数组+Entry数组+单链表
          • Segment继承ReenTrantLock类每一个segment相当于一个锁这就是分段锁
          • 当其它线程进行put操作时发现锁资源被占用时回去进行节点创建避免线程空闲这种思想也叫预创建
          • segment长度固定为16HashEntry可以扩容
        • jdk1.8 和HashMap结构一样
        • CAS + setCtl
      • 如何保证线程安全
      • key和value不支持null的原因
        • 二义性