zoukankan      html  css  js  c++  java
  • Index--复合索引的思考1

    在创建复合索引时,除了考虑索引键的选取外,还需考虑索引键的先后顺序。下面借助一些场景来讲解。


    场景1
    表dbo.UserLoginStats记录每个用户每天的登录统计,目前表中存放10亿数据,每天新增数据500W(每天每个用户很少几条条记录),目前系统有用户8000W,有查询:
    SELECT * FROM dbo.UserLoginStats
    WHERE UserID=@userID
    AND LoginDay=@loginDay

    对于此查询,可以创建索引:

    CREATE INDEX IX_UserID_LoginDay
    ON dbo.UserLoginStats(UserID,LoginDay)

    CREATE INDEX IX_LoginDay_UserID
    ON dbo.UserLoginStats(LoginDay,UserID)

    以上两种索引都可以帮助查询快速返回结果,并且消耗的IO相同,消耗的CPU时间也大致相同,因此对于该查询来说,两个索引没有区别,但我们该使用哪一个查询呢?

    假设索引行每行占用20个字节,每个索引页存放400条记录,则10亿数据需要约2500W个索引页。
    对于索引IX_LoginDay_UserID(LoginDay,UserID):
    每天新增的500W新纪录存放在一起,需要约1.3万个索引页来存放,只需要100MB的内存来存放,在数据读取和写入时,更多的是顺序IO。

    对于索引IX_UserID_LoginDay(UserID,LoginDay):
    每天新增的500W数据需要分散存放到索引的各个页面中,可能影响到数百万的索引页,需要1GB到5GB的内存,在数据读取和写入时,更多的是随机IO。

    因此,在不考虑其他因素影响的条件下,针对该场景,索引IX_LoginDay_UserID(LoginDay,UserID)时最佳的。


    误区:在创建复合索引时,很多人会将选择性较高的列放在前面,
    解释:可选择性是我们在挑选索引键时考虑的一个因素,通常会选择性较高的备选键来创建索引,但不意味该键就应该放在索引前面。


    PS: 在笔者维护的系统中,曾出现过类似问题,在checkpoint时需要写入上万个不连续的数据页,导致很高的磁盘队列,同时还导致在日志备份还原时消耗大量的时间。

    PS2:针对该问题,数据分区和历史数据定期数据归档也是很好的解决办法。

    惯例上图引狼

    图片来源:http://www.douban.com/photos/photo/353424799/

  • 相关阅读:
    CrawlSpiders
    从抓取Tencent中学习Scrapy
    对象返回规范的url的两种方式的两种方式
    多对多关系的额外字段
    Django定时任务
    Scripy学习(一)
    Django开发博客一(搭建模型和准备数据)
    求并集
    求子集、交集
    java数学函数Math类中常用的方法
  • 原文地址:https://www.cnblogs.com/TeyGao/p/3552413.html
Copyright © 2011-2022 走看看