数据库优化策略
个人总结,笔记:
一、硬件方面
在硬件方面了解的不多,总结下来:
- 内存:内存决定了缓存的数据量,主要决定对热数据的访问速度。
- IO优化
- ......
二、sql语句方面
我们所说的sql优化主要是指,sql查询速度。
在sql语句优化这方面也是最节约成本的。
- 以我个人经验来看,建立相应的索引,是最有效的方案。
-
- 聚集索引:例如,汉语字典的“ 拼音 ”,字母是有序的排列,以英文字母“a”开头并以“z”结尾。如果要查 “ 郑 ” 只要找到 “ z ” ,然后在 “ z ” 中找到 “ zheng ” 的拼音。查 “ 安 ” 只要找到 “ a ” 即可 。也就是说,字典的正文部分本身就是一个目录,您不需要再去查其他目录来找到您需要找的内容。我们把这种正文内容本身就是一种按照一定规则排列的目录称为“聚集索引”。
- 非聚集索引: 例如,汉语字典的“ 偏旁部首 ”。如果找 “ 张 ” ,假如“ 张 ” 在678页,而检字表中“张”的上面是“驰”字,对应页码是68页,“张”下的“弩”字对应的页码也可能是700页。“驰”“弩” 并不是真正排列在“张”的上下方。在“ 偏旁部首 ”目录中连续的“驰、张、弩”三字实际上就是他们在非聚集索引中的排序,是字典正文在非聚集索引中的映射。通过这种方式来找到所需要的字,它需要两个过程,先找到目录中的结果,然后翻到对应的页码。我们把这种目录纯粹是目录,正文纯粹是正文的排序方式称为“非聚集索引”。
-
- 何时使用聚集索引或非聚集索引
-
- 参考图
-
建立索引的时候,还是得根据具体业务需要来建立。
-
- 避免全表扫描
-
- 一个我曾经的担忧点:
-
select * from table where name=''zheng'' and id > 10000 和 执行 select * from table1 where id > 10000 and name=''zheng''
曾经以为第一个,先查name=''zheng'' 然后再查 id > 10000,第二个先查id > 10000再查name=''zheng''。事实上,这样的担心是不必要的。SQL SERVER中有一个“查询分析优化器”(个人只是简单了解了一下),它可以计算出where子句中的搜索条件并确定哪个索引能缩小表扫描的搜索空间,也就是说,它能实现自动优化。
-
- 例如 like
如:name like ‘张%’ ,这就属于范围查找,会命中索引
而:name like ‘%张’ ,就属于全表扫描
2. or 会引起全表扫描
3. 典型的情况就是包括非操作符的语句,如:NOT、!=、<>、!<、!>、NOT EXISTS、NOT IN、NOT LIKE等
4. exists 和 in 的执行效率是一样的
5. 用函数charindex()和前面加通配符%的LIKE执行效率一样
6. union并不绝对比or的执行效率高(这里要视情况而定)
select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi=''2004-9-16'' or gid>9990000 全表扫描
但如下,union查询时可以命中索引
select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi=''2004-9-16''
union
select gid,fariqi,neibuyonghu,reader,title from Tgongwen where gid>9990000
查询列是一样的话,那么用union则反倒和用or的执行速度差很多,虽然这里union扫描的是索引,而or扫描的是全表。(这里指的是where后面的查询列)
7. 字段提取要按照“需多少、提多少”的原则,避免“select * from table”
8. order by按聚集索引列排序效率最高
9. 高效的TOP (SQL SERVER数据库)。在查询和提取超大容量的数据集时,影响数据库响应时间的最大因素不是数据查找,而是物理的I/0操作。
10. 后续补充.....
三、分库分表
- 分表:
-
- 垂直分表:将表中的大型字段、不常用的字段拆分出来,通过外键进行关联。表结构改变,对应的数据量可能是一致的。它解决的问题是,加快查询速度,并不能解决高并发这种场景问题。
- 水平分表:将表中数据进行分割(视具体情况定),例如安时间分割,A表存最近一个月内的数据,B表存半年内的数据(通过定时任务同步数据),C表存历史记录。相对来说表中数据越少,查询速度越快。它解决的问题也是,加快查询速度问题,并不能解决高并发这种场景问题。
- .....可能还有更多方案。
-
- 分库 我个人认为,分库还是解决高并发、也包括加快查询、写入或者报表之类。
-
-
- 每个数据库都有“最大连接数”
- 单台服务器有着性能的上限,部署在此服务器上的数据库的增删改查操作速度也有上限。
- 后续补充.....
-
-
垂直拆分数据库
例如:整个系统中的有业务模块,订单模块,用户模块等等都在一个数据库系统,相应的产生数据耦合性高,数据不隔离等问题。大并发的写入、读取操作导致系统性能下降。系统可用性在降低,这些都是需要待解决的,需要将这些数据进行分片,也就是分散开,均摊现有数据库的数据写入、查询压力。
此时,用到数据库的垂直拆分。将数据库以模块为单位拆分,以前集中在一个数据库的读写压力,现在分散到多个数据库中。其一,解决单个数据库的数据存储瓶颈。其二,在大并发情况下,提高数据读写性能。但是,当单表中的数据过大时,查询此表中的数据还是会慢(可以考虑分表了)。
水平拆分数据库
其实水平拆分的核心思想是,将单一数据表数据按照我们约定的某种规则进行拆分到多个数据库和数据表中,我们的关注点是在表数据本身上。感觉多少有些类似水平分表的意思,这里不单单只考虑查询速度问题,还考虑的并发。
常用的按照某一个表的字段的区间做拆分,其中最常用的是“ 日期 ”字段了,例如:表中的创建时间字段,我们要查某个月的数据,可以将对应月份数据放进对应月份表中,这样我们可以根据创建时间定位到数据存储表,然后以相应查询条件进行查询。
主要为解决查询速度、并发。
本文作者:youliCC