7.9—7.10leetcode +数据库调优方法

leetcode落后了一天,今天已经刷了三个题了,学习一下算法框架吧,今天彻底弄懂回溯法。

回溯法其实就是暴力搜索,但是对于回溯法来说可以在每一次循环的时候明确自己的选择,其实就是DFS,BFS广度优先其实就是每一次游走决策的顺序不一样罢了。

//回溯法一般用于搜寻所有答案
result = []

def backtrack(当前路径,可以选择的列表):
    if 当前找到了答案:
        result.add(路径)
        return
    for 选择 in 可以选择的列表:
        做出选择 
        //主要是result和选择列表更新
        
        backtrack(路径,选择列表)
        撤销一下选择
        //路径撤销,选择撤销

//分枝限界
        

这里值得注意的是采用了递归的方式实现了这些算法,如果是有关于树的问题,一般采用栈和队列的方式比较合理。这里聊下去就比较深入了,我们今天浅浅的解析一下全排列问题:

vector<vector<int>> permute(vector<int>& nums) {
        vector<int> track; // 维护已经做出的选择
        vector<bool> used(nums.size(),0); //下一步选什么
        backtrack(nums,track,used);
        return ans;
    }
    void backtrack(vector<int> &nums ,vector<int> &track ,vector<bool> &used){
        if(track.size() == nums.size())
        {
            ans.push_back(track);
            return;
        }

        for(int i = 0 ; i < nums.size() ; i ++)
        {
            if(used[i]) continue;
            track.push_back(nums[i]);
            used[i] = 1;
            backtrack(nums,track,used);
            track.pop_back();
            used[i] = 0;
        }
    }

变形原来数组里面有重复的值,如何保证不重复元素呢?仔细思考一下,回溯法的used已经保证了本身上下之间的不重复,但是如果要保证,去除不同位置则需要在每次的选择列表上下功夫,对于每一次的选择列表进行去重。

 

void backtrack(vector<int> &nums ,vector<int> &track ,vector<bool> &used){
        if(track.size() == nums.size())
        {
            ans.push_back(track);
            return;
        }
        set<int>choice;//集合去重
        for(int i = 0 ; i < nums.size() ; i ++)
        {
            if(!used[i]) choice.insert(nums[i]);
        }


        for(int i = 0 ; i < nums.size(); i ++)
        {
            if(used[i]) continue;

            if(choice.find(nums[i]) == choice.end()) continue;
            track.push_back(nums[i]);

            //使用了这个数字则将其移除选择列表
            choice.erase(nums[i]);

            used[i] = true;
            
            backtrack(nums,track,used);
            track.pop_back();
            used[i] = false;
        }
        }

在之前的内容中,我们了解了数据库事务的基本特性AICD,和ORM框架的基本概念至于实际操作我们在之后的学习中再涉及吧。

今天开始,我们来进入数据库调优的相关内容学习:

首先了解一下数据库的调优目标,简单来说,我们肯定是希望数据库的运行速度变得更快,数据库的并行吞吐量也更大。具体来说如何评判数据库的运行情况呢?

1)用户的反馈

2)日志分析

3)服务器资源监控

4)数据库内部情况监控

调优手段:

1)最高级别,啥也别说了换数据库吧,哈哈哈。那么这里就需要了解不同数据库之间的不同区别,这里也包括了不同的储存引擎。SQL和NoSQL,InnoDB和MyISAM等等,以及列式存储和行存储,这里数据仓库等等,需要根据业务来定。

2) 第二级别,优化表的设计。这里有三范式设计,和反范式设计的设计思想。采用合适的字段类型。

       1NF:字段不可分。
       2NF:非主属性对候选键有着完全依赖关系,就是说一张表不能存在两种关系。
       3NF:不存在两种非间接关系。

反范式设计

主要是为了减少表之间字段冗余和提供一个标准。

3) 优化逻辑查询
记住两个例子,第一个是IN和EXISTS的区别:

IN是外表取出一个元素去查询内表,因此内表越小则越快。

EXISTS(外表里面存在这个行)是内表去查外表,外表越小越快,取出来一个内表的行数据,去外表索引查找。

第二个例子:

 WHERE里面如果对于字段进行计算可能会让索引失效,就是要多使用索引。例如使用通配符而不去使用函数去拼接字符串。左匹配问题。

4)优化物理查询

加索引,如何加索引?

1. 重复度过高,索引其实没啥必要,哈希碰撞过高。
2. 不要使得查询语句让索引失效。
3. 联合索引
4. 多个索引的使用,索引过多会使得优化器对索引评估时间过多。

5)使用Redis或者Memcached作为缓存(空间局部性)

6)库级优化
读写业务分离,表分库等等
 


索引:

1)数据量较小的时候,索引效率一般。

2)前面说过男女不应该创建索引,但是如果有一方的数量很少,则创建索引很快就能查询。

四种索引内容:

1) 普通索引,对字段建立哈希,MySQL只支持英文。
2) 唯一索引(可以为空,数据必须唯一,不产生哈希冲突),(3) 主键索引(非空)
4) 全文索引

物理实现方式:

1)聚集索引:索引指向的数据是按照主键来排序存储数据。

2)非聚集索引: 索引指向的数据是随机存储的,非聚集索引不会把数据直接放到索引后面,而是维护了单独的索引表。叶子节点装的是主键或者聚集索引的字段。

  1. 聚集索引的叶子节点存储的就是我们的数据记录,非聚集索引的叶子节点存储的是数据位置。非聚集索引不会影响数据表的物理存储顺序。
  2. 一个表只能有一个聚集索引,因为只能有一种排序存储的方式,但可以有多个非聚集索引,也就是多个索引目录提供数据检索。
  3. 使用聚集索引的时候,数据的查询效率高,但如果对数据进行插入,删除,更新等操作,效率会比非聚集索引低。

联合索引以及最左匹配原则:

联合索引存在最左匹配原则,也就是按照最左优先的方式进行索引的匹配。比如刚才举例的 (x, y, z),如果查询条件是 WHERE x=1 AND y=2 AND z=3,就可以匹配上联合索引;如果查询条件是 WHERE y=2,就无法匹配上联合索引。


数据库的数据结构B+树:平衡多路搜索树

HASH冲突

  1. Hash 索引不能进行范围查询,而 B+ 树可以。这是因为 Hash 索引指向的数据是无序的,而 B+ 树的叶子节点是个有序的链表。
  2. Hash 索引不支持联合索引的最左侧原则(即联合索引的部分索引无法使用),而 B+ 树可以。对于联合索引来说,Hash 索引在计算 Hash 值的时候是将索引键合并后再一起计算 Hash 值,所以不会针对每个索引单独计算 Hash 值。因此如果用到联合索引的一个或者几个索引时,联合索引无法被利用。
  3. Hash 索引不支持 ORDER BY 排序,因为 Hash 索引指向的数据是无序的,因此无法起到排序优化的作用,而 B+ 树索引数据是有序的,可以起到对该字段 ORDER BY 排序优化的作用。同理,我们也无法用 Hash 索引进行模糊查询,而 B+ 树使用 LIKE 进行模糊查询的时候,LIKE 后面前模糊查询(比如 % 开头)的话就可以起到优化作用。

  • 19
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值