精华内容
下载资源
问答
  • 数据库索引设计(基础篇)

    千次阅读 2020-10-08 09:05:06
    点击蓝色“有关SQL”关注我哟加个“星标”,天天与10000人一起快乐成长索引数据库中,毋庸置疑扮演了极其重要的角色。在这篇文章中,我们即将要讨论这些和索引相关的事情:优化器是如何选择...

    点击蓝色“有关SQL”关注我哟

    加个“星标”,天天与10000人一起快乐成长

    索引在数据库中,毋庸置疑扮演了极其重要的角色。

    在这篇文章中,我们即将要讨论这些和索引相关的事情:

    1. 优化器是如何选择索引的;

    2. 应该如何正确的建立索引;

    3. 如何判断优化器选择了正确的索引;

    4. 如何找出哪些已经不再被使用的索引;

    简介:

    索引可以帮助查询更快的定位到所需的记录上,从而避免整表扫描。如果索引引用的列,可以完全包含查询所需的字段,这类索引叫做 覆盖索引(convering index),完全不用回读(针对非聚集索引表)便可满足查询需求。一些常规需求,比如排序,分组和 distinct 都可以有效利用索引。

    这里有个概念特别要注意,回读。官方给出的正式名称,叫做 bookmark lookup. 在 SQL Server 中,有两种形式的表存在:聚集索引表和堆表(clustered index 和 heap table).为表建立的非聚集索引,叶子节点存储的除了索引值,还有指向原表的 RID(file id + page id + row id)或者聚集索引值。一旦查询使用到了索引,而索引包含的列中,找不到查询需要的列,那么优化器会给出访问原表的方法,即用索引存储的 RID 或者键值,回到原表去读一边。此时的读,被称为回读,用的是随机读(random read), 一次磁头的转动假如就为一条记录,实际上却扫描了一个扇区,由此可见有多么浪费资源。

    索引选用机制

    B-Tree(Balanced Tree),索引引入它的目的就是为了建立快速查询的结构。索引数据页的叶子节点页,有可能并不是按照逻辑顺序排好序的,因为有碎片冲刷,长时间数据页是被打散了的。此时按照这种页码去扫描,出来的结果肯定是不对的。因此引入 B-Tree, 即确保了索引最终提供正确的逻辑顺序,也加快了速度。

    (摘自:https://use-the-index-luke.com/sql/anatomy/the-tree)

    上面的 [46,53,57,83]是B-Tree 中的一个节点,此节点上的数据必须保证时时刻刻都按照索引顺序排列,SQL Server 靠锁来维持对这些节点的独占。正因为这些节点保证了数据的顺序性,因此底层索引数据页就不用严格按照索引顺序排列了,由第二底层的数据页指针,指向最终存储的索引数据页,就可以保证逻辑的顺序正确了。

    索引的使用,一般是和条件查询绑定的。如果想要发挥索引的作用,就必须用已经被索引的字段做条件查询。比如以下这些判断条件语句,是可以有效利用索引的:

    1. ProductID = 771

    2. UnitPrice<3.975

    3. LastName='Allen'

    4. LastName LIKE 'Brown%'

    总结一下,等值比较或不等值比较,包括 =,<,>,<=,>=,!=,!<,!>,BETWEEN 和 In,执行计划都可以安排索引作为数据访问的途径。但以下表达式,却会阻扰索引的使用:

    1. ABS(ProductID)=771

    2. UnitPrice + 1 <3.975

    3. LastName LIKE '%Allen'

    4. UPPER(LastName) = 'Allen'

    我们只需比较两者的执行计划,就可以知道,判断条件的字段上加了函数或者表达式,索引就无法再使用了。

    Predicate 表达式中,一旦索引字段(ProductID) 加了 abs() 函数,索引就失效了。

    多列组合索引,情况就会复杂一些。当前列的条件判断是否能有效利用索引,取决于前一列使用的条件判断是否是等值判断。比如下列的判断条件,SQL Server 都是可以利用索引对两列字段做 seek 操作的,前提是索引按照判断条件字段的前后顺序建立的:(

    以下的场景,均假设了按顺序建立了 ProductID + SalesOrderID, LastName + FirstName 的索引)

    ProductID = 771 AND SalesOrderID > 34000
    LastName = 'Smith' AND FirstName = 'lan' 
    

    当第二列使用了函数或者复杂表达式,或者第一列使用了复杂表达式,那么就仅仅能使用索引去做第一列的 seek:

    ProductID = 771 AND ABS(SalesOrderID) = 34000
    ProductID < 771 AND SalesOrderID = 34000 
    LastName >'Smith' AND FirstName = 'lan'
    

    又或者前一列用了函数或者表达式,那么整个索引就失效了:

    ABS(ProductID) = 771 AND SalesOrderID = 34000 
    LastName LIKE '%Smith' AND FirstName='lan'
    

    看下第一列可以走索引的 seek 而第二列却不能利用 seek 的例子:

    SELECT ProductID, SalesOrderID, SalesOrderDetailID 
    FROM Sales.SalesOrderDetail 
    WHERE ProductID = 771 AND ABS(SalesOrderID) = 45233
    

    注意:Seek Predicates 显示有效利用了索引第一列 ProductID 的条件判断,而 Predicate 就显示索引第二列无法使用 seek 操作

    数据库引擎优化顾问(The Database Engine Tuning Advisor)

    大多数的商业数据库都会提供一个优化组件,帮助建立有效的索引。SQL Server 中这个组件就是数据库引擎优化顾问(The Database Engine Tunning Advisor). 理论上可以有两种架构来设计这个优化顾问,一种是新建一个成本模型估算成本,另一种是利用现有的查询优化器来估算成本。新建一个优化器除去一些复杂的操作和部署不说,基于新成本模型估算出来的执行计划,显然也不会给现有的优化器来用,现有的优化器始终还是以自己得到的执行计划去操作数据。因此,宝都押在利用现有查询优化器来做出优化评估。

    SQL Server 是第一家搭载物理对象设计器的商业数据库,从 SQL Server 7.0 开始使用 Index Tuning Wizard 到 SQL Server 2005 替换成了 Database Engine Tuning Advisor( DTA). 两个产品都使用了优化器本身的成本估算模型去分析当前优化策略。目的就是为了达到高度自治和调优。除了索引以外,DTA 也可以帮助引导建立物化视图( indexed view) 和 分区(partition)。

    当然优化顾问只是评估,并不会自动替人工去创建索引。那么不建立索引的情况下,优化顾问是怎么去评估,得出一个合理的索引?其实本质上优化器选择哪一个索引,完全建立在元数据以及字段的 statistics 之上,在优化的过程中,索引数据存在不存在不重要。索引一旦选择完毕,在执行的时候,一定需要索引数据必须存在。

    开启优化顾问,当然会对数据库的性能有一定额影响,所以安排好适当时间。

    所以在 DTA(Database Engine Tuning Advisor) 调优的过程中,SQL Server 不会真的去创建 DTA 认为完美的索引,而是给出一种叫做假设索引(hypothetical index),这类索引在 SQL Server 7 的 Index Tuning Wizard 当中也有用过。就如名字一样,hypothetical index 不是一种真实的索引,不以任何形式存在于数据库中,因为 DTA 一旦用完,这些索引就被丢弃了。他们只包含 statistics,只能用未归档的 CREATE INDEX 语句的 WITH STATISTICS_ONLY 选项来创建,且这个命令只有在 SQL Server Profiler 里面看得到。

    下面看个简单的例子,用来找出索引没有正确创建的场景。

    1)  创建一张新表,没有任何索引存在

    SELECT * 
      INTO dbo.SalesOrderDetail 
    FROM Sales.SalesOrderDetail
    

    2)  将下面的查询保存成文件

    SELECT * 
    FROM dbo.SalesOrderDetail 
    WHERE ProductID = 897
    

    3)  使用 DTA 来辅助分析缺少的索引

    如上图所示,打开 DTA(Database Engine Tuning Advisor),在 Workload File 选项下面,定位到刚才新建的文件;选择需要测试的数据库 AdventureWorks; 点击 Start Analysis 命令执行。

    等待 DTA 完成,打开这张表分析:

    SELECT * 
    FROM msdb..DTA_reports_query
    

    由此可见 ,DTA 帮我们推荐了个新的索引,据此索引生成的执行计划,成本只有 0.00332754. 而当前环境下,成本居然高达 1.24414. 通过打开预估执行计划窗口,这成本可以很容易得到。

    我们根据 DTA 推荐的 Index Recommendations 创建索引,之后再执行上面的条件查询,很显然效率高很多。

    hypothetical index 还可以通过 WITH STATISTICS_ONLY 创建:

    CREATE CLUSTERED INDEX clx_ProductID
     ON dbo.SalesOrderDetail(ProductID)
    WITH STATISTICS_ONLY
    

    查询索引的字典表:

    SELECT name,type_desc,is_hypothetical
    FROM sys.indexes 
    WHERE object_id = object_id(N'dbo.SalesOrderDetail')
      AND name = 'cix_ProductID'
    

     

    这里的 is_hypothetical 是 1, 代表的是一个假设的索引,并不真正存在。

    Missing Indexes Feature(特性)

    除了 DTA(Database Engine Tuning Advisor), SQL Server 还提供了一种方法来检测哪些索引对当前的查询是用的。这种方法称为 Missing Index  特性。这个方法不需要 DBA 去判断是否要进行调优,不需要严格指定请求文件,它很轻量,早在 SQL Server 2005 就已经推出来了。

    在优化过程中,查询优化器会自动填补一个最优的索引,如果这个索引不存在,会在 xml 执行计划或者 GUI 执行计划里突出显示出来,并且会在缓冲中一直保留到下次重启,通过查询 sys.dm_db_missing_index 动态性能视图就可以看到统计情况。当优化器提示徐亚更好的索引满足查询时,实际上它在告诉我们两件事:1)当前的执行计划不是最优的;2)应该考虑新建索引来满足当前查询。当然, missing index 有自己不足,后面会讲到,更详细的解说可以参考官方在线文档, limitations of the Missing indexes Feature.

    通过下面的这个小例子,我们一起探讨下 missing index 的使用场景:

    如果你是从上面的例子一路看下来的,请 drop 表 dbo.SalesOrderDetail。

    1)新建表 dbo.SalesOrderDetail

    SELECT * 
      INTO dbo.SalesOrderDetail 
    FROM Sales.SalesOrderDetail
    

    2) 运行下面的查询

    SELECT * 
    FROM dbo.SalesOrderDetail 
    WHERE SalesOrderID = 43670 AND SalesOrderDetailID > 112
    

    通过查询运行时执行计划及其属性,可知这类查询被称作 TRIVIAL optimization level.

    针对 TRIVIAL 级别的计划,查询优化器并不会给出最优的索引(基于哪个列,按照什么顺序)。由上图可见, GUI 并没有提示缺少什么样的索引。

    基于此,我们可以通过增加无关的索引,来避免查询优化器评定查询为 TRIVIAL 级别。如下:

    CREATE INDEX IX_ProductID
     ON dbo.SalesOrderDetail(ProductID)
    
    
    

    此时,我们已经可以看到 GUI 提示“缺少索引”的告警了,且 Optimization Level 为 FULL.

    这里解释下,什么是 trivial plan. 一句话概括就是简单的不能再简单的查询计划。比如:

    SELECT ProductID 
    FROM dbo.SalesOrderDetail 
    WHERE ProductID = 987
    

    刚才我们已经在表 dbo.SalesOrderDetail 上面以 ProductID 字段为索引键,创建了索引 IX_ProductID. 因此仅查询 ProductID 且有条件表达式时,不再需要其他复杂的判断,走 index seek 即可。此时,执行计划就被称为 trivial plan.

    处理了 trivial plan 的尴尬,剩下的事情,就是按照提示,我们判断这索引是不是要加,还是修改之前的索引,使其符合当下的查询:

    SELECT * 
    FROM dbo.SalesOrderDetail 
    WHERE SalesOrderID = 43670 AND SalesOrderDetailID > 112
    

    在 [MissingIndexes] 栏位下,我们可以看到 Impact, MissingIndex, Optimization Level 三个大栏。

    1. Impact 是指 missing index 能在多大程序上影响现有的查询;

    2. Missing Index 给出了优化器建议的索引字段和索引顺序;

    3. Optimization Level 如果显示了 FULL, 表达的意思就是有优化调整空间

    按照提示,我们新建索引:

    CREATE INDEX IDX_ORD_DETAIL_ID 
    ON dbo.SalesOrderDetail(SalesOrderID,SalesOrderDetailID)
    

    再执行上面的语句 :

    SELECT * 
    FROM dbo.SalesOrderDetail 
    WHERE SalesOrderID = 43670 AND SalesOrderDetailID > 112
    

    对比前后执行计划,这一次索引真排上用场了:

    无用的索引(Unused Indexes)

    在应用系统中,总有些表,索引,存储过程随着管理的松懈,慢慢遗留了下来。如何对这些无用(不再用)的数据库对象做处理,便成为了难题。本章讨论如何对无用的索引做处理。

    为什么要处理掉这些无用的索引呢?首先,索引是表一样存在的数据库对象,占用了数据库磁盘空间;第二,在更新数据表的时候,索引会实时更新,对并发性能产生很大影响;第三,大量的索引,给优化器带来很大的运算压力。

    判断索引无用的方法,核心是使用一张动态性能试图(DMV: Dynamic Management View), 即 sys.dm_db_index_usage_stats.

    这张试图记录了所有 seek, scan, lookup, update 等操作的次数,还有最后一次的执行时间。除了索引(非聚集索引)使用频次统计之外,还有包括堆表和聚集表。和 sys.indexes 里面的规定一致,index_id 为 0 的即为堆表,index_id 为 1 的即为聚集索引表,大于等于 2 的为非聚集索引,这些 index_id 为 2 的索引才是我们要考虑去移除的。想想为什么?

    SELECT object_name(object_id) as tblName
        ,    index_id 
        ,    user_seeks
        ,    user_scans 
        ,    user_lookups
        ,    user_updates
    FROM sys.dm_db_index_usage_stats WITH(NOLOCK)
    

    --完--

    往期精彩:

    本号精华合集(二)

    如何写好 5000 行的 SQL 代码

    如何提高阅读 SQL 源代码的快感

    我在面试数据库工程师候选人时,常问的一些题

    零基础 SQL 数据库小白,从入门到精通的学习路线与书单

    展开全文
  • 数据库】MySQL索引分析

    千次阅读 多人点赞 2021-11-04 21:30:48
    文章目录索引索引的理解索引优缺点索引的分类索引的基本操作索引结构数据加载(B+树的原因)总结索引优化没必要建立索引的场景索引失效的场景隐式类型转换问题联合索引违反最左前缀匹配原则对索引列运算is null 判断...

    索引

    一种能帮助mysql提高查询效率的数据结构:索引数据结构

    “索引(在MySQL中也叫“键key”)是存储引擎快速找到记录的一种数据结构。”

    ——《高性能MySQL》

    索引的理解

    • 索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针。
    • 索引是对数据库表中的一列或多列的值进行排序的一种数据结构
    • 索引的作用就类似于书本的目录,新华字典的拼音,偏旁部首的首查字,可以快速的检索到需要的内容,所以当数据达到几百万的时候,那么索引就很有必要了。其功能是帮助我们快速匹配查找到需要的数据行,是数据库性能优化最常用的工具之一

    索引优缺点

    优点

    • 1.大大加快数据的检索速度;
    • 2.创建唯一性索引,保证数据库表中每一行数据的唯一性;
    • 3.加速表和表之间的连接;
    • 4.在使用分组和排序子句进行数据检索时,可以显著减少查询中分组和排序的时间。

    缺点

    • 1.索引需要占用数据表以外的物理存储空间
    • 2.创建索引和维护索引要花费一定的时间,维护索引需要耗费数据库资源,并且要占用磁盘空间
    • 3.当对表进行更新操作时,索引需要被重建,这样降低了数据的维护速度。

    结论:数据库表并不是索引加的越多越好,而是仅为那些常用的搜索字段建立索引效果才是最佳的!

    索引的分类

    • 主键索引:PRIMARY KEY
      设定为逐渐后,数据库自动建立索引,innodb为聚簇索引,主键索引列值不能有空(Null)

    • 单值索引:又叫单列索引、普通索引
      一个索引只包含单个列,一个表可以有多个单列索引

    • 唯一索引:
      索引列的值必须唯一,但允许有空值(Null),但只允许有一个空值(Null)

    • 复合索引:又叫组合索引

      一个索引可以包含多个列,多个列共同构成一个复合索引!

    • 全文索引:Full Text (MySQL5.7之前,只有MYISAM存储引擎支持全文索引
      全文索引类型为FULLTEXT,在定义索引的列上支持值的全文查找,允许在这些索引列中插入重复值和空值。全文索引可以在Char 、Varchar 上创建。

    索引的基本操作

    SHOW INDEX FROM table_name;#查看索引详情:
    
    1. 主键索引 PRIMARY KEY

    它是一种特殊的唯一索引,不允许有空值。一般是在建表的时候同时创建主键索引,直接在字段后面加PRIMARY KEY。注意:一个表只能有一个主键。

    1. 唯一索引 UNIQUE

    唯一索引列的值必须唯一,但允许有空值。

    ALTER TABLE 表名 ADD UNIQUE 索引名 ON (列名)	#修改表结构添加
    CREATE UNIQUE INDEX 索引名 ON 表名(列名)		#直接创建
    

    如果是唯一组合索引,则列值的组合必须唯一。

    ALTER TABLE 表名 ADD UNIQUE 索引名 (列名1,列名2) #修改表结构添加
    CREATE UNIQUE INDEX 索引名 ON 表名(列名1,列名2)		#直接创建
    
    1. 普通索引 INDEX:这是最基本的索引,命令如下
    ALTER TABLE 表名 ADD INDEX  ON (列名)	 #修改表结构添加
    CREATE INDEX 索引名 ON 表名(列名)	#直接创建
    
    1. 组合索引 INDEX:即一个索引包含多个列,多用于避免回表查询,命令如下

    指多个字段上创建的索引,只有在查询条件中使用了创建索引时的第一个字段,索引才会被使用。使用组合索引时遵循最左前缀集合

    ALTER TABLE 表名 ADD INDEX 索引名 (列名1,列名2);
    CREATE INDEX 索引名 ON 表名(列名1,列名2);
    
    
    -- 复合索引查询的2个原则
    -- 1.最左前缀原则
    -- eg: 创建复合索引时,字段的顺序为 name,age,birthday
    -- 在查询时能利用上索引的查询条件为: 
    SELECT * FROM t_user3 WHERE name = ?
    SELECT * FROM t_user3 WHERE name = ? AND age = ?
    SELECT * FROM t_user3 WHERE name = ? AND birthday = ?
    SELECT * FROM t_user3 WHERE name = ? AND age = ? AND birthday = ?
    -- 而其他顺序则不满足最左前缀原则:
    ... WHERE name = ? AND birthday = ? AND age = ? -- 不满足最左前缀原则
    ... WHERE name = ? AND birthday = ? -- 不满足最左前缀原则
    ... WHERE birthday = ? AND age = ? AND name = ? -- 不满足最左前缀原则
    ... WHERE age = ? AND birthday = ? -- 不满足最左前缀原则
    
    
    -- 2.MySQL 引擎在执行查询时,为了更好地利用索引,在查询过程中会动态调整查询字段的顺序!
    -- 这时候再来看上面不满足最左前缀原则的四种情况:
    -- 不满足最左前缀原则,但经过动态调整顺序后,变为:name age birthday 可以利用复合索引!
    ... WHERE name = ? AND birthday = ? AND age = ? 
    -- 不满足最左前缀原则,也不能动态调整(因为缺少age字段),不可以利用复合索引!
    ... WHERE name = ? AND birthday = ? 
    -- 不满足最左前缀原则,但经过动态调整顺序后,变为:name age birthday 可以利用复合索引!
    ... WHERE birthday = ? AND age = ? AND name = ?
    -- 不满足最左前缀原则,也不能动态调整(因为缺少name字段),不可以利用复合索引!
    ... WHERE age = ? AND birthday = ?
    
    1. 全文索引 FULLTEXT:也称全文检索,是目前搜索引擎使用的一种关键技术,命令如下
    ALTER TABLE 表名 ADD FULLTEXT 索引名 (列名);
    CREATE FULLTEXT INDEX 索引名 ON 表名(列名)
    

    删除索引命令

    DROP INDEX <索引名> ON <表名>
    

    索引一经创建不能修改,如果要修改索引,只能删除重建。

    索引结构

    1. FULLTEXT
      即为全文索引,其可以在CREATE TABLE ,ALTER TABLE ,CREATE INDEX 使用,不过目前只有 CHAR、VARCHAR ,TEXT 列上可以创建全文索引。全文索引并不是和MyISAM一起诞生的,它的出现是为了解决WHERE name LIKE “%word%"这类针对文本的模糊查询效率较低的问题。

    2. HASH
      由于HASH的唯一(几乎100%的唯一)及类似键值对的形式,很适合作为索引。HASH索引可以一次定位,不需要像树形索引那样逐层查找,因此具有极高的效率。但是,这种高效是有条件的,即只在“=”和“in”条件下高效,对于范围查询、排序及组合索引仍然效率不高。

    3. BTREE
      BTREE索引就是一种将索引值按一定的算法,存入一个树形的数据结构中(二叉树),每次查询都是从树的入口root开始,依次遍历node,获取leaf。这是MySQL里默认和最常用的索引类型。

    4. RTREE
      RTREE在MySQL很少使用,仅支持geometry数据类型,支持该类型的存储引擎只有MyISAM、BDb、InnoDb、NDb、Archive几种。

    BTREE索引就是一种将索引值按一定的算法,存入一个树形的数据结构中
    BTREE又分两种,一种是B-TREE,如下图

    在这里插入图片描述

    另外一种是B+TREE,结构如下图

    在这里插入图片描述

    B+Tree相对于B-Tree有几点不同:

    • B+Tree非叶子节点只存储键值信息。
    • B+Tree所有叶子节点之间都有一个链指针。
    • B+Tree数据记录都存放在叶子节点中。

    B 树和 B+ 树在数据结构上其实有一些类似,它们都可以按照某些顺序对索引中的内容进行遍历,对于排序和范围查询等操作,B 树和 B+ 树相比于哈希会带来更好的性能,当然如果索引建立不够好或者 SQL 查询非常复杂,依然会导致全表扫描。

    与 B 树和 B+ 树相比,哈希作为底层的数据结构的表能够以 O(1) 的速度处理单个数据行的增删改查,但是面对范围查询或者排序时就会导致全表扫描的结果,而 B 树和 B+ 树虽然在单数据行的增删查改上需要 O(log n) 的时间,但是它会将索引列相近的数据按顺序存储,所以能够避免全表扫描

    数据加载(B+树的原因)

    既然使用哈希无法应对我们常见的 SQL 中排序和范围查询等操作,而 B 树和 B 树和 B+ 树都可以相对高效地执行这些查询,那么为什么我们不选择 B 树呢?这个原因其实非常简单 —— 计算机在读写文件时会以页为单位将数据加载到内存中。页的大小可能会根据操作系统的不同而发生变化,不过在大多数的操作系统中,页的大小都是 4KB

    当我们需要在数据库中查询数据时,CPU 会发现当前数据位于磁盘而不是内存中,这时就会触发 I/O 操作将数据加载到内存中进行访问,数据的加载都是以页的维度进行加载的,然而将数据从磁盘读取到内存中所需要的成本是非常大的,普通磁盘(非 SSD)加载数据需要经过队列、寻道、旋转以及传输的这些过程,大概要花费 10ms 左右的时间。

    我们在估算 MySQL 的查询时就可以使用 10ms 这个数量级对随机 I/O 占用的时间进行估算,这里想要说的是随机 I/O 对于 MySQL 的查询性能影响会非常大,而顺序读取磁盘中的数据时速度可以达到 40MB/s,这两者的性能差距有几个数量级,由此我们也应该尽量减少随机 I/O 的次数,这样才能提高性能。数据库系统的设计者巧妙利用了磁盘预读原理将一个节点的大小设为等于一个页,这样每个节点只需要一次I/O就可以完全载入

    B 树与 B+ 树的最大区别就是,B 树可以在非叶结点中存储数据,但是 B+ 树的所有数据其实都存储在叶子节点中,当一个表底层的数据结构是 B 树时,假设我们需要访问所有『大于 4,并且小于 9 的数据』:

    在这里插入图片描述

    如果不考虑任何优化,在上面的简单 B 树中我们需要进行 4 次磁盘的随机 I/O才能找到所有满足条件的数据行:

    1. 加载根节点所在的页,发现根节点的第一个元素是 6,大于 4;
    2. 通过根节点的指针加载左子节点所在的页,遍历页面中的数据,找到 5;
    3. 重新加载根节点所在的页,发现根节点不包含第二个元素;
    4. 通过根节点的指针加载右子节点所在的页,遍历页面中的数据,找到 7 和 8;

    当然我们可以通过各种方式来对上述的过程进行优化,不过 B 树能做的优化 B+ 树基本都可以,所以我们不需要考虑优化 B 树而带来的收益,直接来看看什么样的优化 B+ 树可以做,而 B 树不行

    由于所有的节点都可能包含目标数据,我们总是要从根节点向下遍历子树查找满足条件的数据行,这个特点带来了大量的随机 I/O,也是 B 树最大的性能问题。

    B+ 树中就不存在这个问题了,因为所有的数据行都存储在叶节点中,而这些叶节点可以通过『指针』依次按顺序连接,当我们在如下所示的 B+ 树遍历数据时可以直接在多个子节点之间进行跳转,这样能够节省大量的磁盘 I/O 时间,也不需要在不同层级的节点之间对数据进行拼接和排序;通过一个 B+ 树最左侧的叶子节点,我们可以像链表一样遍历整个树中的全部数据,我们也可以引入双向链表保证倒序遍历时的性能

    在这里插入图片描述

    但是使用 B+ 树这种数据结构会增加树的高度从而增加整体的耗时,然而高度为 3 的 B+ 树就能够存储千万级别的数据,实践中 B+ 树的高度最多也就 4 或者 5,所以这并不是影响性能的根本问题。

    总结

    MySQL 默认的存储引擎选择 B+ 树而不是哈希或者 B 树的原因:

    • 哈希虽然能够提供 O(1) 的单数据行操作性能,但是对于范围查询和排序却无法很好地支持,最终导致全表扫描;
    • B 树能够在非叶节点中存储数据,但是这也导致在查询连续数据时可能会带来更多的随机 I/O,而 B+ 树的所有叶节点可以通过指针相互连接,能够减少顺序遍历时产生的额外随机 I/O;

    索引优化

    没必要建立索引的场景

    1. 字段的唯一性差,比如性别,只有男、女两种,没有必要建索引
    2. 频繁更新的字段不用,因为索引频繁更新有性能损耗
    3. where 中不用的字段没必要建索引
    4. B+ 树索引在搜索可为 NULL的列时索引性能不好,通常在建表时会将字段置为 NOT NULL ,并指定 DEFAULT默认值

    索引失效的场景

    隐式类型转换问题

    如果表字段定义的类型为字符串char,但是在搜索时指定的 where条件传入的参数却是数字类型INT,那么会存在 隐式类型转换的问题,从而造成不走索引的慢查询

    联合索引违反最左前缀匹配原则

    联合索引违反了最左前缀匹配原则,例如建立了联合索引 (a, b, c),以下使用都会有问题

    违反最左前缀匹配原则
    where b = 1 and c = 1
    联合索引 b 的范围查询会使范围条件字段之后的索引失效,导致之后 c 字段没有使用到索引,也就是只用到了索引 a 和 b,联合索引部分失效
    where a = 1 and b > 1 order by c
    
    对索引列运算

    对索引列的运算会导致索引失效,应该避免

    运算符含义
    +
    -
    *
    /除以
    !=、<>不等于
    %取余
    is null 判断

    is null| is not null | 都会导致索引失效

    like 使用不当

    like 查询 ‘name%’ 的百分号加在右边才走索引,可以使用覆盖索引来避免 ‘%name%’ 查询索引失效

    对索引列使用函数

    例如select * from template t where ROUND(t.logicdb_id) = 1,不会走索引列,这种情况下应该建立基于函数的索引,如 ROUND(t.logicdb_id)

    in 使用不当

    in 查询肯定会走索引,但是当 in 的取值范围较大而表数据较少时会导致索引失效,走全表扫描,该情况与下文 1.9 节类似。如果使用了 not in,则不走索引

    使用不当

    条件中有or,即使其中有部分字段带索引也不会使用,要想使用or又想让索引生效,只能将 or 条件中的每个列都加上索引

    查询优化不走索引

    对于数据量比较小的表,如果 MySQL 查询优化时认为全表扫描更快时也不会走索引

    总结
    1. 有or必全有索引;
    2. 复合索引未用左列字段;
    3. like以%开头;
    4. 需要类型转换;
    5. where中索引列有运算;
    6. where中索引列使用了函数;
    7. 如果mysql觉得全表扫描更快时(数据少)

    约束以及分类

    作用:是为了保证数据的完整性而实现的摘自一套机制,即(约束是针对表中数据记录的)

    MySQL中的约束:

    • 非空约束:NOT NULL 保证某列数据不能存储NULL 值;
    • 唯一约束:UNIQUE(字段名) 保证所约束的字段,数据必须是唯一的,允许数据是空值(Null),但只允许有一个空值(Null);
    • 主键约束:PRIMARY KEY(字段名) 主键约束= 非空约束 + 唯一约束 保证某列数据不能为空且唯一;
    • 外键约束:FOREIGN KEY(字段名) 保证一个表中某个字段的数据匹配另一个表中的某个字段,可以建立表与表直接的联系;
    • 自增约束:AUTO_INCREMENT 保证表中新插入数据时,某个字段数据可以依次递增;
    • 默认约束:DEFALUT 保证表中新插入数据时,如果某个字段未被赋值,则会有默认初始化值;
    • 检查性约束:CHECK 保证列中的数据必须符合指定的条件;

    MySQL索引和约束的区别

    • 索引的作用:索引用于快速定位特定数据,提高查询效率的。
    • 约束的作用:约束是为了保证数据的完整性,即约束是针对表中数据记录的。
    • 总结:约束是为了保证表数据的完整性,索引是为了提高查询效率,两者作用不一样!种类也不太一样!

    MySQL中InnoDB表的聚簇索引

    每个InnoDB表都需要一个聚簇索引。该聚簇索引可以帮助表优化增删改查操作。

    • 如果你为表定义了一个主键,MySQL将使用主键作为聚簇索引。

    • 如果你不为表指定一个主键,MySQL讲索第一个组成列都not null的唯一索引作为聚簇索引。

    • 如果InnoBD表没有主键且没有适合的唯一索引(没有构成该唯一索引的所有列都NOT NULL),MySQL将自动创建一个隐藏的名字为“GEN_CLUST_INDEX ”的聚簇索引。

    因此每个InnoDB表都有且仅有一个聚簇索引。

    所有不是聚簇索引的索引都叫非聚簇索引或者辅助索引。

    在InnDB存储引擎中,每个辅助索引的每条记录都包含主键,也包含非聚簇索引指定的列。

    MySQL使用这个主键值来检索局促索引。因此应该尽可能将主键缩短,否则辅助索引占用空间会更大。

    一般来说用自增的整数型列作为主键列。

    简单解释
    聚簇索引和非聚簇索引
    在这里插入图片描述

    举例聚簇索引和非聚簇索引的区别。

    注意:这里的主键是非自增的。普通索引K表示普通的索引 非 唯一索引。

    在这里插入图片描述

    主键是采用B+Tree的数据结构(请看左图),根据上文可以知主键为聚簇索引,物理存储是根据ID的增加排序递增连续存储的。

    普通索引K也是B+Tree的数据结构(请看右图),但是它不是聚簇索引,因此为非聚簇索引或者辅助索引(聚簇索引只可能是主键,或者所有组成唯一键的所有列都为NOT NULL的第一个唯一索引,或者隐式创建的聚簇索引这三种情况)。他的叶子节点存储的是索引列的值,它的数据域是聚簇索引即ID。

    假如普通索引k为非唯一索引,要查询k=3的数据。需要在k索引查找k=3得到id=30。然后在左侧的ID索引树查找ID=30对应的记录R3。

    然后K索引树继续向右查找,发现下一个是k=5不满足(非唯一索引后面有可能有相等的值,因此向右查找到第一个不等于3的地方),停止。

    整个过程从K索引树到主键索引树的过程叫做回表

    非聚簇索引检索数据时,检索一次本树再去聚簇索引树中检索一次,这样二次检索树结构,那么为什么不直接在非聚簇索引树叶子节点中存放行数据物理地址,这样只需要检索一次树结构就拿到行数据呢?

    当在做新增数据时,因为底层是需要基于主键索引进行排序的,那么就可能导致原来某些数据对应的物理地址发生了变化,而这时候由于我们的非聚簇索引树的叶子节点直接存储了数据的物理地址,所以为了保证能获取到数据,还需要同时对非聚簇索引树叶子节点的地址进行一遍更新修改!

    也就是说:之所以不在非聚簇索引树的叶子节点直接存放行数据的物理地址,是因为,存储数据的物理地址会随着数据库表的CRUD操作而不断变更,为了保证能获取到数据,这时必须要对非聚簇索引树相关叶子节点的地址进行一遍修改!而存主键,主键不会随着CRUD操作发生变化,宁愿多查一次树,也不要再修改一次树的结构!

    每次使用辅助索引检索都需要经过2次B+树查找,看上去聚簇索引的效率明显要低于非聚簇索引,那么聚簇索引的优势何在呢?

    - 1.由于行数据和聚簇索引树的叶子节点存储在一起,同一页中会有多条行数据,首次访问数据页中某条行记录时,会把该数据页数据加载到Buffer(缓存器)中,当再次访问该数据页中其他记录时,不必访问磁盘而直接在内存中完成访问。
    -- 注:主键id和行数据一起被载入内存,找到对应的叶子节点就可以将行数据返回了,如果按照主键id来组织数据,获取数据效率更快!
    
    -- 2.辅助索引的叶子节点,存储主键的值,而不是行数据的存放地址。这样做的好处是,因为叶子节点存放的是主键值,其占据的存储空间小于存放行数据物理地址的储存空间
    

    为什么主键通常建议使用自增id?

    -- 聚簇索引树存放数据的物理地址(xx1,xx2,xx3,xxx5)与索引顺序(1,2,3,5)是一致的,即:
    -- 1.只要索引是相邻的,那么在磁盘上索引对应的行数据存放地址也是相邻的。
    -- 2.如果主键是自增,那么当插入新数据时,只需要按照顺序在磁盘上开辟新物理地址存储新增行数据即可。
    -- 3.而如果不是主键自增,那么当新插入数据后,会对索引进行重新排序(重新调整B+树结构),磁盘上的物理存储地址也需要重新分配要存储的行数据!
    

    参考博客
    路飞:MySQL索引分析以及相关面试题
    MySQL/Oracle数据库优化总结(非常全面)
    MySQL数据库:SQL优化与索引优化
    MySQL聚簇索引和非聚簇索引的理解
    为什么 MySQL 使用 B+ 树

    展开全文
  • 看sqlserver执行计划的时候有时会看到这样一行小绿字: 它会告诉你当前sql应该在哪些列上建索引(还有include列),建完之后能提升多少性能。对于特别复杂的sql,这个建议有时还是很方便的。那么这些数据是从哪查...

    看sqlserver执行计划的时候有时会看到这样一行小绿字:

    它会告诉你当前sql应该在哪些列上建索引(还有include列),建完之后能提升多少性能。对于特别复杂的sql,这个建议有时还是很方便的。那么这些数据是从哪查出来的?

    sqlserver有四个索引缺失相关的视图:

    • sys.dm_db_missing_index_details
    • sys.dm_db_missing_index_columns(index_handle)
    • sys.dm_db_missing_index_groups
    • sys.dm_db_missing_index_group_stats

    以上视图返回的信息会在查询优化器优化查询时更新,因而不是持久化的,缺失的索引信息只保留到重新启动SQL Server前。如果要在服务器回收后保留缺失索引信息,则应定期进行备份。

     

    1. sys.dm_db_missing_index_details

    返回有关缺失索引的详细信息,不包括空间索引。针对的是SQLSERVER从启动以来所有运行的语句,而不是某一个查询。

    列名数据类型描述
    index_handleint标识特定的缺失索引,该标识符在服务器中是唯一的
    database_idsmallint标识带有缺失索引的表所在的数据库
    object_idint标识索引缺失的表
    equality_columnsnvarchar(4000)构成相等谓词的列的逗号分隔列表,谓词的形式如下:
    where table.column =constant_value
    inequality_columnsnvarchar(4000)构成不等谓词的列的逗号分隔列表,谓词的形式如下:
    where table.column > constant_value
    “=”之外的任何比较运算符都表示不相等。
    included_columnsnvarchar(4000)应该加在索引include部分的列。对于内存优化的索引 (包括哈希和内存优化非聚集),忽略included_columns。 每个内存优化索引中均包含表的所有列。
    statementnvarchar(4000)索引缺失的表的名称。

     

    2. sys.dm_db_missing_index_columns(index_handle)

    这是个动态管理函数,返回与缺少索引(不包括空间索引)的数据库表列有关的信息。

    列名数据类型描述
    column_idint列的 ID。
    column_namesysname表列的名称。
    column_usagevarchar(20)查询使用列的方式。 可能的值及其说明是:
    equality:table.column = constant_value
    inequality:table.column > constant_value。 “=”之外的任何比较运算符都表示不相等。
    include:用于索引的include列
    select * from sys.dm_db_missing_index_columns(54);

    返回的内容含义跟第一个视图类似,但是可读性稍微没那么好。比如根据上图,sqlserver的建议是:在ProductID上创建索引,SalesOrderID作为包含性列的索引。

    CREATE INDEX idx_SalesOrderDetail_test_ProductID_IncludeIndex ON SalesOrderDetail_test(ProductID) INCLUDE(SalesOrderID);

     

    3. sys.dm_db_missing_index_groups

    返回有关特定缺失索引组中包含的缺失索引的信息,不包括空间索引(感觉没太大用处)

    列名数据类型描述
    index_group_handleint标识缺失索引组。
    index_handleint标识缺失索引所属由指定的组index_group_handle

    一个索引组仅包含一个索引。

     

    4. sys.dm_db_missing_index_group_stats

    返回缺失索引组的摘要信息,不包括空间索引。最主要是avg_user_impact这个字段,告诉你增加了这个缺失索引,性能可以提高的百分比。

    列名数据类型描述
    group_handleint标识缺失索引组。 此标识符在服务器中是唯一的。
    其他列提供有关组中的索引被视为缺失的所有查询的信息。
    一个索引组仅包含一个索引。
    unique_compilesbigint将从该缺失索引组受益的编译和重新编译数。 许多不同查询的编译和重新编译可影响该列值。
    user_seeksbigint由可能使用了组中建议索引的用户查询所导致的查找次数。
    user_scansbigint由可能使用了组中建议索引的用户查询所导致的扫描次数。
    last_user_seekdatetime由可能使用了组中建议索引的用户查询所导致的上次查找日期和时间。
    last_user_scandatetime由可能使用了组中建议索引的用户查询所导致的上次扫描日期和时间。
    avg_total_user_costfloat可通过组中的索引减少的用户查询的平均成本。
    avg_user_impactfloat实现此缺失索引组后,用户查询可能获得的平均百分比收益。 该值表示如果实现此缺失索引组,则查询成本将按此百分比平均下降。
    system_seeksbigint由可能使用了组中建议索引的系统查询(如自动统计信息查询)所导致的查找次数。 有关详细信息,请参阅Auto Stats 事件类
    system_scansbigint由可能使用了组中建议索引的系统查询所导致的扫描次数。
    last_system_seekdatetime由可能使用了组中建议索引的系统查询所导致的上次系统查找日期和时间。
    last_system_scandatetime由可能使用了组中建议索引的系统查询所导致的上次系统扫描日期和时间。
    avg_total_system_costfloat可通过组中的索引减少的系统查询的平均成本。
    avg_system_impactfloat实现此缺失索引组后,系统查询可能获得的平均百分比收益。 该值表示如果实现此缺失索引组,则查询成本将按此百分比平均下降。

     

    参考

    https://docs.microsoft.com/zh-cn/sql/relational-databases/system-dynamic-management-views/sys-dm-db-missing-index-group-stats-transact-sql?view=sql-server-ver15

    展开全文
  • SQL优化:找到缺少索引

    千次阅读 2019-01-17 12:16:56
    这篇文章要讲的是SQL Server对系统中运行的sql进行监控,把系统中缺少索引信息保存下来,提供给我们查询。 我们根据这些辅助的信息,结合实际的情况,比如:表上已经有的索引,涉及到的字段,以及具体的sql,判断...

    上篇文章讲了如何查询索引的使用情况,前提是索引已经创建了。

    这篇文章要讲的是SQL Server对系统中运行的sql进行监控,把系统中缺少的索引信息保存下来,提供给我们查询。

    我们根据这些辅助的信息,结合实际的情况,比如:表上已经有的索引,涉及到的字段,以及具体的sql,判断如果创建了这些索引,是否真的能提高性能,如果真的能提高性能,就可以创建这些索引。

    通过查询3个视图,可以了解如果创建了这个索引,对性能有多大的提升(Improvement_Measure ):

    sys.dm_db_missing_index_groups

    sys.dm_db_missing_index_group_stats

    sys.dm_db_missing_index_details

    代码如下:

    SELECT TOP 30
             ROUND(s.avg_total_user_cost * s.avg_user_impact * ( s.user_seeks
                                                                 + s.user_scans ),
                   0) AS [Total Cost] ,
             s.avg_total_user_cost * ( s.avg_user_impact / 100.0 ) * ( s.user_seeks
                                                                   + s.user_scans ) AS Improvement_Measure ,
             DB_NAME() AS DatabaseName ,
             d.[statement] AS [Table Name] ,
             equality_columns ,
             inequality_columns ,
             included_columns
     FROM    sys.dm_db_missing_index_groups g
             INNER JOIN sys.dm_db_missing_index_group_stats s ON s.group_handle = g.index_group_handle
             INNER JOIN sys.dm_db_missing_index_details d ON d.index_handle = g.index_handle
     WHERE   s.avg_total_user_cost * ( s.avg_user_impact / 100.0 ) * ( s.user_seeks
                                                                   + s.user_scans ) > 10
     ORDER BY [Total Cost] DESC ,
             s.avg_total_user_cost * s.avg_user_impact * ( s.user_seeks
                                                           + s.user_scans ) DESC
    

     

    展开全文
  • SQL索引数据库优化中占有一个非常大的比例, 一个好的索引的设计,可以让你的效率提高几十甚至几百倍,在这里将带你一步步揭开他的神秘面纱。 1.1 什么是索引? SQL索引有两种,聚集索引和非聚集索引索引主要...
  • 今天和大家简单聊下Mongo数据库索引。 Mongo索引是基于B-tree,存储在一个易于遍历读取的数据集合中,它是对数据库表中一列或多列的值进行排序的一种结构。 数据库索引和我们书籍目录相似,有了索引,我们不需要...
  • 作者:潇湘隐者 在ORACLE数据库中,定义外键约束时,ORACLE是...外键缺失索引影响外键列上缺少索引会带来三个问题,限制并发性、影响性能、还有可能造成死锁。所以对于绝大部分场景,我们应该尽量考虑在外键上面创建索
  • 数据库索引统计信息

    2014-03-08 13:30:14
    查询优化器使用这些统计信息并通过估计使用索引评估查询的开销来确定最佳查询计划。 创建统计信息后,数据库引擎对列值(根据这些值创建统计信息)进行排序,并根据这些值(最多 200 个,按间隔分隔开)创建一个...
  • 浅谈oracle数据库索引

    千次阅读 2015-03-11 20:39:28
    在关系型数据库中,索引是一种和表有关的数据结构,它可以使查询的sql语句执行的更快。其实索引就如同图书的目录,我们可以根据目录中的页码快速的找到所需的内容。 编写一本书,只有章节内容定好之后再设置目录;...
  • 数据库视图和索引

    2013-04-24 15:56:50
    视图是由多个字段列和数据行构成,这些行和列来自一个或多个物理数据表,但并不在数据库中以存储的数据表形式存在。 所以视图是一个虚拟表,被引用的表称为基表。 视图的使用是为了方便频繁使用的多表查询。 ...
  • SQL索引数据库优化中占有一个非常大的比例, 一个好的索引的设计,可以让你的效率提高几十甚至几百倍,在这里将带你一步步揭开他的神秘面纱。  1.1 什么是索引?  SQL索引有两种,聚集索引和非聚集索引,...
  • 数据库索引学习

    千次阅读 2015-07-31 01:11:55
    数据库索引理论原理学习,为什么加索引速度更快,IO读更快操作更少,加索引注意事项,哪些场景下索引可以用到或者用不到
  • 实验名称 实验7 索引数据库安全 日期 2020年 6 月 19 日 一、实验目的: (1)理解索引的概念与类型。 (2)掌握使用SQL Server Management Studio创建与维护索引的方法。 (3)掌握T-SQL语句创建与维护索引...
  • <br />索引其实关键目的是为了加快检索速度而建立的,所以,怎么用索引数据库系统本身的事情,作为数据库设计或使用者,设计并创建好索引然后体验加上索引后的查询变快的感觉就行了。所以,索引怎么用就变为...
  • mysql 索引加锁分析

    2020-04-21 14:41:05
    mysql 索引加锁分析背景MVCC:Snapshot Read vs Current ReadCluster Index:聚簇索引2PL:Two-Phase LockingIsolation Level一条简单SQL的加锁实现分析组合一:id主键+RC组合二:id唯一索引+RC组合三:id非唯一索引...
  • 文章目录1. 绪论1.1. 数据库4个基本概念1.1.1. 数据1.1.2. 数据库1.1.3. 数据库管理系统(DBMS)1.1.4. 数据库系统(DBS)1.2. 数据管理1.2.1. 发展过程1.2.2. 三个阶段对比1.2.3. 数据库系统特...
  • 实施工程师面试题(答案)

    万次阅读 多人点赞 2019-06-21 11:33:32
    触发器是针对数据表(库)的特殊的存储过程,当这个表发生了 Insert、Update或Delete操作时,数据库就会自动执行触发器所定义的SQL语句,从而确保对数据的处理必须符合这些SQL语句所定义的规则。 14、SQL 数据库...
  • 运维工作梳理

    千次阅读 多人点赞 2019-12-19 07:44:12
    在他运转的过程中,对他进行维护,他集合了网络、系统、数据库、开发、安全、监控于一身的技术。 运维又包括很多种,有DBA运维、网站运维、虚拟化运维、监控运维、游戏运维等等。 运维分类: 1)开发运维:是给...
  • http://blog.csdn.net/u013378306/article/details/50761610为防止原文删除特此备份--------------------——————————————————————————————首先说一下是从MySQL数据库导入数据这里使用...
  • Oracle数据库索引

    千次阅读 2015-08-18 15:33:26
    Oracle数据库索引  本文标签:Oracle数据库 索引   导读:数据库在当代社会中的地位是越来越高,干什么都似乎离不开数据库,所以,掌握好数据库是在社会中立足的条件 。如果你在数据库方面是一个新手,又...
  • 参考教材:数据库系统概论 第五版(王珊萨师煊版本) 文章目录1. 绪论1.1. 数据库系统概述1.2. 什么是数据管理1.3. 数据库系统与人工管理、文件系统比1.4. 数据库系统特点1.5. 数据模型1.6. 数据库系统模式的概念...
  • oracle数据库索引

    千次阅读 2017-10-12 19:24:00
    在关系型数据库中,索引是一种和表有关的数据结构,它可以使查询的sql语句执行的更快。其实索引就如同图书的目录,我们可以根据目录中的页码快速的找到所需的内容。 编写一本书,只有章节内容定好之后再设置目录;...
  • 因为对索引不是很熟悉,所以测试得到结果没有任何价值,甚至有些误导人,这边说声抱歉,在哪跌倒在哪爬起来。 应用场景 还是用商品表(Product)作为示例,表结构如下: 存在这样一种业务场景:获取某个供应商...
  • 前端面试题

    万次阅读 多人点赞 2019-08-08 11:49:01
    当一个DOM节点被点击时候,我们希望能够执行一个函数,应该怎么做? 53 看下列代码输出为何?解释原因。 54 看下列代码,输出什么?解释原因。 54 看下列代码,输出什么?解释原因。 54 看代码给答案。 56 ...
  • 人们往往会忽略的是,并行处理也可以加快索引处理的速度,从而提高数据库服务器的整体性能。 使用IBM DB2 for i,可以使用CPU进行索引处理。 特别是,当基础数据更改时,创建索引以及维护索引时,DB2 for i可以使用...
  • 对于数据库来说,索引是一个必选项,但对于现在的各种大型数据库来说,索引可以大大提高数据库的性能,以至于它变成了数据库不可缺少的一部分。索引分类:逻辑分类single column or concatenated 对一列或多列建所...
  • 软件测试面试题汇总

    万次阅读 多人点赞 2018-09-27 12:31:09
    转载自: ... 软件测试面试题汇总 测试技术面试题 ...........................................................................................................
  • 商业数据库中,很多新版本都可以自动创建索引,给出索引创建的建议,并且以此作为卖点,ORACLE ,SQL SERVER 均有类似的功能,实际上通过查询语句,与全表扫描的语句,与谓词的比对...
  • 数据库索引

    2013-12-11 11:09:31
    一、索引是什么 索引是与表或视图关联的磁盘上结构,可以加快从表或视图中检索行的速度。索引包含由表或视图中的一列或多列生成的键。这些键存储在一个结构(B 树)中,使 SQL Server 可以快速有效地查找与键值关联...
  • 在关系数据库中,索引是一种与表有关的数据库结构,它可以使对应于表的SQL语句执行得更快。索引的作用相当于图书的目录,可以根据目录中的页码快速找到所需的内容。  对于数据库来说,索引是一个必选项,但对于...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 24,668
精华内容 9,867
关键字:

数据库执行缺少索引