zoukankan      html  css  js  c++  java
  • SQLSERVER的 筛选索引(Fiter Index)

      fiter index(筛选索引)是SQL Server的一项功能,可使此数据库与众不同。

    筛选索引的概念

    SQL Server中常用的索引是一种物理结构,它包含来自所有行的一组选定列的值 在一张桌子里。大多数情况下,结构是一个b树,值存储在节点和叶子中,以便在树中查找(寻找)特定值非常快。它从根开始,然后通过节点决定每次选择哪个分支。尽管这是一个充满激情的话题,但我不会完全描述索引的结构。出于本文的目的,足以知道索引列中的每个值在b树中都有自己的位置。如果表很大,则索引列具有许多值,并且索引具有许多节点。向表中添加新行会使表更大,但索引也会增长。有一些或多或少的明显后果:

    1. 索引增长并消耗更多磁盘空间。
    2. 更大的索引更难以搜索 - 搜索和扫描速度更慢。
    3. 重建大型索引需要更多时间和资源。

    索引是一个很好的发明。它使得寻找(寻找特定价值)成为可能。如果列已建立索引,则数据库不需要从表中读取所有行,以在索引列中查找具有特定值的行。然而,大指数是大问题。有时您知道该表有一些您不会查询的特定行。如果我可以索引不是所有行而只是索引它们的一部分怎么办?这正是筛选索引。

    没有索引的示例

    我有一个表,其中包含用户发送给其他用户的消息。当接收器读取消息时,通过将mes_unread字段从1 切换为0将其标记为已读

    表中有100万行。当用户登录他/她的帐户时,将显示未读消息。这种情况的直接影响是非常频繁的查询是以下一种:

     

    目前,此表上只有一个索引 - mes_id上的聚簇索引因此,毫不奇怪,样本运行的执行计划显示聚集索引扫描正在读取所有数据,以查找与条件匹配的行。

    
    

     执行计划没有索引

    估计的查询成本为10.6818最常用的查询从表中读取所有行并不好。

    使用sp_spaceused过程检查表的大小

    EXEC  sp_spaceused'user_messages  ' ;

    大小没有索引 

    它显示表数据消耗了大约103 MB的存储空间和聚集索引 - 392 KB。

    传统方法

    回到聚集索引扫描问题,有一个简单的解决方案 - 创建一个索引。例如,数据库引擎建议的那个在执行计划中显示绿色字体

    CREATE NONCLUSTERED INDEX IX_mes_receiver_usr_id_unread 
    ON user_messages(mes_receiver_usr_id,mes_unread);

    创建索引后,相同的查询执行效率更高。执行计划显示使用索引和键查找搜索操作替换扫描操作。

    执行计划索引

    查询的成本估计为1.20738它比没有索引的要少9倍。

    sp_spaceused报告用于存储索引的额外15 MB。

    规模指数

    15 MB并不多,但表只需103 MB。如果表是10 GB,我可以预期索引是1.5 GB,这是显而易见的。那还有什么方法可以减少这个索引的数据量吗?

    过滤索引的方法

    假如应用用户非常活跃,他们通常在收到消息后立即阅读消息,因此大部分消息已被阅读(95%)。只有5%的消息尚未打开。这意味着该条件  AND mes_unread = 1 将返回的行数减少了20倍(至5%)。更进一步,我不需要索引的那部分包含有关mes_unread = 0的行的信息幸运的是,SQL Server包含过滤的索引功能,它允许我减少用于构建索引的行数。

    此时,我将用过滤索引替换当前索引。

    DROP INDEX IX_mes_receiver_usr_id_unread ON user_messages;
    CREATE NONCLUSTERED INDEX IX_mes_receiver_usr_id_unread 
    ON user_messages(mes_receiver_usr_id,mes_unread)
    WHERE mes_unread = 1;

    过滤的索引可以通过定义中的WHERE子句轻松识别。上面使用的构造在两列上创建索引:mes_receiver_usr_idmes_unread,
    仅适用于mes_unread = 1的那些行。不包括与其不匹配的其他行。它们根本不占用索引中的磁盘空间。
    在开始使用过滤索引之前,我将检查执行计划。

    它看起来与普通索引的执行计划非常相似。那有什么区别?

    不同的是执行成本。它下降到0.246134  ,几乎是传统指数的五倍。

    为什么?答案是索引大小,可以使用sp_spaceused检查

    EXEC  sp_spaceused'user_messages  ' ;

    大小过滤指数

    与传统索引的15 MB相比,过滤索引的1.1 MB明显更少。它直接回答了较小的执行成本 - 更小的索引,更少的IO,更快的搜索。


    总结下使用情况:

    案件  执行成本 索引大小 
    没有索引 10.6818 -
    普通索引 1.2073 15.3 MB
    过滤索引 0.2461 1.1 MB

    它可能是一个优势:更小的存储使用,更快的搜索,

    但也有一个缺点 - 更改WHERE子句中的值可能会使索引无用。例如,如果我想查询已经读过的消息,那么这个索引对我没用:

    SELECT * 
    FROM user_messages
    WHERE mes_receiver_usr_id = 234
    AND mes_unread = 0;



    size filter index2

    如您所见,将条件从mes_unread = 1更改mes_unread = 0会导致从搜索切换到扫描。此时原因应该是显而易见的 -

    过滤后的索引没有关于mes_unread = 0的行的任何信息,因此无法使用。

    结论

    过滤的索引具有强大的功能。如果您拥有几乎从不查询大多数行的表,它们可以提供很多帮助。它们不仅消耗更少的存储空间,而且由于它们更小,它们也更快。另一方面,我很少使用过滤索引。当想知道为什么时,我得出的结论是,如果绝大多数行都没有被查询为什么要保留它们?

  • 相关阅读:
    1988-B. 有序集合
    1987-A. 集训队选拔
    1964-NP
    1963-带妹子去看电影
    1962-Fibonacci
    1961-计算机基础知识大赛 2 (new)
    TCP/IP协议详解 卷一:协议 18章、TCP连接的建立与终止
    3、剑指offer--从尾到头打印链表
    2、剑指offer--替换空格
    1、剑指offer--二维数组中查找
  • 原文地址:https://www.cnblogs.com/monkeybron/p/9559043.html
Copyright © 2011-2022 走看看