SQL必知必会
陈旸
清华大学计算机博士
立即订阅
10179 人已学习
课程目录
已完结 49 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词丨SQL可能是你掌握的最有用的技能
免费
第一章:SQL语法基础篇 (19讲)
01丨了解SQL:一门半衰期很长的语言
02丨DBMS的前世今生
03丨学会用数据库的方式思考SQL是如何执行的
04丨使用DDL创建数据库&数据表时需要注意什么?
05丨检索数据:你还在SELECT * 么?
06丨数据过滤:SQL数据过滤都有哪些方法?
07丨什么是SQL函数?为什么使用SQL函数可能会带来问题?
08丨什么是SQL的聚集函数,如何利用它们汇总表的数据?
09丨子查询:子查询的种类都有哪些,如何提高子查询的性能?
10丨常用的SQL标准有哪些,在SQL92中是如何使用连接的?
11丨SQL99是如何使用连接的,与SQL92的区别是什么?
12丨视图在SQL中的作用是什么,它是怎样工作的?
13丨什么是存储过程,在实际项目中用得多么?
14丨什么是事务处理,如何使用COMMIT和ROLLBACK进行操作?
15丨初识事务隔离:隔离的级别有哪些,它们都解决了哪些异常问题?
16丨游标:当我们需要逐条处理数据时,该怎么做?
17丨如何使用Python操作MySQL?
18丨SQLAlchemy:如何使用Python ORM框架来操作MySQL?
19丨基础篇总结:如何理解查询优化、通配符以及存储过程?
第二章:SQL性能优化篇 (18讲)
20丨当我们思考数据库调优的时候,都有哪些维度可以选择?
21丨范式设计:数据表的范式有哪些,3NF指的是什么?
22丨反范式设计:3NF有什么不足,为什么有时候需要反范式设计?
23丨索引的概览:用还是不用索引,这是一个问题
24丨索引的原理:我们为什么用B+树来做索引?
25丨Hash索引的底层原理是什么?
26丨索引的使用原则:如何通过索引让SQL查询效率最大化?
27丨从数据页的角度理解B+树查询
28丨从磁盘I/O的角度理解SQL查询的成本
29丨为什么没有理想的索引?
30丨锁:悲观锁和乐观锁是什么?
31丨为什么大部分RDBMS都会支持MVCC?
32丨查询优化器是如何工作的?
33丨如何使用性能分析工具定位SQL执行慢的原因?
34丨答疑篇:关于索引以及缓冲池的一些解惑
35丨数据库主从同步的作用是什么,如何解决数据不一致问题?
36丨数据库没有备份,没有使用Binlog的情况下,如何恢复数据?
37丨SQL注入:你的SQL是如何被注入的?
第三章:认识DBMS (7讲)
38丨如何在Excel中使用SQL语言?
39丨WebSQL:如何在H5中存储一个本地数据库?
40丨SQLite:为什么微信用SQLite存储聊天记录?
41丨初识Redis:Redis为什么会这么快?
42丨如何使用Redis来实现多用户抢票问题
43丨如何使用Redis搭建玩家排行榜?
44丨DBMS篇总结和答疑:用SQLite做词云
第四章:SQL项目实战 (3讲)
45丨数据清洗:如何使用SQL对数据进行清洗?
46丨数据集成:如何对各种数据库进行集成和转换?
47丨如何利用SQL对零售数据进行分析?
结束语 (1讲)
结束语 | 互联网的下半场是数据驱动的时代
SQL必知必会
登录|注册

29丨为什么没有理想的索引?

陈旸 2019-08-16
我之前讲过页这个结构,表和索引都会存储在页中,不同的 DBMS 默认的页的大小是不同的,同时我们也了解到 DBMS 会有缓冲池的机制,在缓冲池里需要有足够多的空间,存储经常被使用到的页,尽可能减少直接的磁盘 I/O 操作。这种策略对 SQL 查询的底层执行来说非常重要,可以从物理层面上最大程度提升 SQL 的查询效率。
但同时我们还需要关注索引的设计,如果只是针对 SQL 查询,我们是可以设计出理想的索引的,不过在实际工作中这种理想的索引往往会带来更多的资源消耗。这是为什么呢?今天我们就来对这部分内容进行学习,内容包括以下几个部分:
什么是索引片?如何计算过滤因子?
设计索引的时候,可以遵循哪些原则呢?
为什么理想的索引很难在实际工作中应用起来?

索引片和过滤因子

索引片就是 SQL 查询语句在执行中需要扫描的一个索引片段,我们会根据索引片中包含的匹配列的数量不同,将索引分成窄索引(比如包含索引列数为 1 或 2)和宽索引(包含的索引列数大于 2)。
如果索引片越宽,那么需要顺序扫描的索引页就越多;如果索引片越窄,就会减少索引访问的开销。比如在 product_comment 数据表中,我们将 comment_id 设置为主键,然后执行下面的 SQL 查询语句:
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《SQL必知必会》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(17)

  • 老毕
    按照对课程的理解,我觉得应该只为use_id字段建立一个窄索引。

    理由如下:

    如果不加思索地套用三星索引,应该这样做:
    1. 有范围谓词,把user_id加到索引中;
    2. 无排序操作,无需添加排序字段到索引中;
    3. 为避免回表,把comment_text添加到索引中。

    这样实际形成宽索引: comment_id + comment_text + user_id

    但是,这样真的划算吗?

    comment_text有可能是长字符串,不但占用较大的索引空间,且有高昂的索引维护成本;如果仅仅建立前缀索引,又无法避免回表操作。

    更重要的是,此索引满足不了长文本的查询需求,左匹配原则限制了它的用途——我们不大可能使用起始字符串去搜索一段评论——全文索引更为适用。

    因此,comment_text不能发挥索引的本来作用。如果仅仅为了避免回表,就将字段一股脑儿塞到索引中,可说是本末倒置了。

    综上,为user_id建立索引,形成comment_id + user_id的窄索引,是应对题中SQL查询的正确方法。
    2019-08-16
    17
  • 大牛凯
    有个问题不太明白,宽索引就是联合索引吗?复合索引又是啥意思?

    作者回复: 宽索引就是联合索引,因为索引列数大于1了,联合索引也就是复合索引,英文composite indexes

    2019-08-16
    1
    3
  • Coool
    下面的0.1%应该换成100%吧。。
    100% x 14% x 54%=8%
    2019-10-25
    1
  • 空知
    联合过滤条件那是不是多写了个 0.1%呀?
    2019-08-30
    1
  • 我不会算法
    通过宽索引来避免回表,指的是覆盖索引吗?按照文中对宽索引的描述,感觉宽索引就是联合索引(复合索引)

    作者回复: 对的 宽索引就是联合索引(复合索引)。避免回表是因为索引覆盖了,所以才会避免回表

    2019-08-24
    1
  • 安静的boy
    请问下三星索引第一条中的等值谓词,怎么样才算等值谓词呢?
    2019-08-16
    1
    1
  • 业余草
    (8)SELECT (9)DISTINCT (11)<Top Num> <select list>
    (1)FROM [left_table]
    (3)<join_type> JOIN <right_table>
    (2)ON <join_condition>
    (4)WHERE <where_condition>
    (5)GROUP BY <group_by_list>
    (6)WITH <CUBE | RollUP>
    (7)HAVING <having_condition>
    (10)ORDER BY <order_by_list>
    老师,这个sql执行顺序,是不是不对啊?
    我在 https://www.xttblog.com 看到的,请老师解惑!
    2019-08-16
    1
  • 书痕
    感觉三星索引简直是面向查询新建了个表嘛~

    作者回复: 差不多 可以这么理解

    2019-11-06
  • 雪飞鸿
    在 MySQL InnoDB 中,系统默认单个索引长度最大为 767 bytes。这里的索引长度指的是索引中所包含字段的大小吗?

    作者回复: 对的

    2019-10-24
  • Ryoma
    4 个问题:
    0:0.1 % * 14% * 54% = 8% 这个数学实在在没搞懂。
    1:窄索引图中 id user_id,这个 id 字段从哪冒出来的
    2:宽窄索引的定义是从哪来的,感觉联合索引、非联合索引定义反而更清晰
    3:老师的问题可以在下一篇回答么?最近撸下来感觉很多同学都有这个需求,这也是另外一门 MySQL 课程的做法,可以借鉴一下。
    2019-09-19
  • wonderq_gk
    如何设置宽索引啊???不告诉方法???

    作者回复: 宽索引,窄索引都是相对于建立的索引包括的列数而言的,当索引的列数超过2列时就是宽索引。

    2019-08-29
    1
  • KEEPUP
    “如果 up_limit_id < trx_id < low_limit_id,说明该行记录所在的事务 trx_id 在目前 creator_trx_id 这个事务创建的时候,可能还处于活跃的状态,因此我们需要在 trx_ids 集合中进行遍历,如果 trx_id 存在于 trx_ids 集合中,证明这个事务 trx_id 还处于活跃状态,不可见。否则,如果 trx_id 不存在于 trx_ids 集合中,证明事务 trx_id 已经提交了,该行记录可见。”
    不明白为什么还会出现否则这种情况,up_limit_id < trx_id < low_limit_id 的话,trx_id不就一定在trx_ids的集合里边吗?
    2019-08-27
  • ABC
    有一些开源的系统,包括我们公司的系统,都在使用uuid作为表的主键。。。

    另外我记得MongoDB也是用的类似uuid做的主键
    2019-08-16
    2
  • asdf100
    疑问:针对窄索引的定义是1或者2个字段,这个如何区分?1个字段是指主键,2个字段是指除pk键以外的一个字段吗?
    2019-08-16
  • asdf100
    针对 先 GROUP BY ,再ORDER BY 的场景,虽然索引有顺序,但仍无法保证ORDER BY的顺序和索引的一样的,这个时间,ORDER BY 如何处理,是不是仍需要 sort buffer进行排序?
    2019-08-16
    1
  • 阿锋
    这一章有点抽象,例子不是很多,索引片概念不理解,如何设置窄索引,宽索引。容易与之前介绍的索引种类弄混,究竟与之前介绍的索引存在什么关系。
    2019-08-16
    2
  • ahazxc
    试用三星索引,可以减少磁盘i/o,避免回表查询。但同时,有利也有弊,三星索引,如果查询列,过滤列字段过多,会导致索引变大,一个索引页能存储的索引变少,所以遍历索引页花的时间就会多,得不偿失

    作者回复: 对的 凡事都有利弊,当我们了解更多的时候,也会了解每种方法的优缺点,选择适合的来使用

    2019-08-16
收起评论
17
返回
顶部