阿里P7架构师面试:大型网站应用之海量数据、高并发解决方案( 三 )


| 1 | 2 | 3 |
| 1 | 4 | 2 |
| 1 | 1 | 4 |
| 2 | 3 | 5 |
| 2 | 4 | 4 |
| 2 | 4 | 6 |
| 2 | 5 | 5 |
其实联合索引的查找就跟查字典是一样的,先根据第一个字母查,然后再根据第二个字母查,或者只根据第一个字母查,但是不能跳过第一个字母从第二个字母开始查 。这就是所谓的最左前缀原理 。
最左前缀原理
我们再来详细介绍一下联合索引的查询 。还是上面例子,我们在(a,b,c)字段上建了一个联合索引,所以这个索引是先按a 再按b 再按c进行排列的,所以:
以下的查询方式都可以用到索引:
select * from table where a=1;
select * from table where a=1 and b=2;
select * from table where a=1 and b=2 and c=3;
上面三个查询按照 (a ), (a,b ),(a,b,c )的顺序都可以利用到索引,这就是最左前缀匹配 。
如果查询语句是:
select * from table where a=1 and c=3;那么只会用到索引a 。如果查询语句是:
select * from table where b=2 and c=3;因为没有用到最左前缀a,所以这个查询是用不到索引的 。如果用到了最左前缀,但是顺序颠倒会用到索引码?
比如:
select * from table where b=2 and a=1;select * from table where b=2 and a=1 and c=3;如果用到了最左前缀而只是颠倒了顺序,也是可以用到索引的,因为mysql查询优化器会判断纠正这条sql语句该以什么样的顺序执行效率最高,最后才生成真正的执行计划 。但我们还是最好按照索引顺序来查询,这样查询优化器就不用重新编译了 。
3.2、索引优化策略

  • 最左前缀匹配原则
  • 主键外检一定要建索引
  • 对 where,on,group by,order by 中出现的列使用索引
  • 尽量选择区分度高的列作为索引,区分度的公式是count(distinct col)/count(*),表示字段不重复的比例,比例越大我们扫描的记录数越少,唯一键的区分度是1,而一些状态、性别字段可能在大数据面前区分度就是0
  • 对较小的数据列使用索引,这样会使索引文件更小,同时内存中也可以装载更多的索引键
  • 索引列不能参与计算,保持列“干净”,比如from_unixtime(create_time) = ’2014-05-29’就不能使用到索引,原因很简单,b+树中存的都是数据表中的字段值,但进行检索时,需要把所有元素都应用函数才能比较,显然成本太大 。所以语句应该写成create_time = unix_timestamp(’2014-05-29’);
  • 为较长的字符串使用前缀索引
  • 尽量的扩展索引,不要新建索引 。比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可
  • 不要过多创建索引, 权衡索引个数与DML之间关系,DML也就是插入、删除数据操作 。这里需要权衡一个问题,建立索引的目的是为了提高查询效率的,但建立的索引过多,会影响插入、删除数据的速度,因为我们修改的表数据,索引也需要进行调整重建
  • 对于like查询,”%”不要放在前面 。
  • 查询where条件数据类型不匹配也无法使用索引,字符串与数字比较不使用索引;
高并发情况下的解决方案
  1. 应用程序和静态资源文件进行分离
  2. 页面缓存
  3. 集群与分布式
  4. 反向代理
  5. CDN
1、应用程序和静态资源文件进行分离
所谓的静态资源就是我们网站中用到的Html、Css、Js、Image、Video、Gif等静态资源 。应用程序和静态资源文件进行分离也是常见的前后端分离的解决方案,应用服务只提供相应的数据服务,静态资源部署在指定的服务器上(Nginx服务器或者是CDN服务器上),前端界面通过Angular JS或者Node JS提供的路由技术访问应用服务器的具体服务获取相应的数据在前端游览器上进行渲染 。这样可以在很大程度上减轻后端服务器的压力 。例如,百度主页使用的图片就是单独的一个域名服务器上进行部署的
2、页面缓存
页面缓存是将应用生成的很少发生数据变化的页面缓存起来,这样就不需要每次都重新生成页面了,从而节省大量CPU资源,如果将缓存的页面放到内存中速度就更快 。
可以使用Nginx提供的缓存功能,或者可以使用专门的页面缓存服务器Squid 。
3、集群与分布式
4、反向代理
5、CDN




推荐阅读