精华内容
下载资源
问答
  • 数据库优化手段

    千次阅读 2017-08-14 09:55:58
    程序员级别的优化有哪些手段?  (1)数据库的设置:如果你的数据库记录数不会超过30万条?如果你的数据库记录超过100万条?该如何设置数据库?一个或多个?  (2)数据库表的设置:当你的某个数据库表记录超过...

    程序员级别的优化有哪些手段? 

    (1)数据库的设置:如果你的数据库记录数不会超过30万条?如果你的数据库记录超过100万条?该如何设置数据库?一个或多个? 
    (2)数据库表的设置:当你的某个数据库表记录超过100万级别,而且每天大量增长,这是一个不得不考虑的问题。如果你的系统浏览量很大,即使是30万条记录也是需要考虑的。 
    (3)索引的使用:索引可以大大提高数据库访问速度。什么时候用?哪些字段使用? 
    (4)存储过程的使用:存储过程终归是比较好的,但是如果需要维护成百上千的存储过程,未必是划算的工程。 
    (5)高效的分页技术:数据库记录分页列表是大量必须使用的基本技术,怎样的分页是快速的? 

    宗旨你需要从上述5个方面考虑数据库的优化。 

    什么时候需要数据库优化? 
    (1)编写代码之前; 
    (2)系统速度慢了的时候; 

    下面就是一些具体的优化技巧了。 

    (1)超大量记录数据库的优化技巧 

    如果你的数据库表记录有超过100万级别,而且不断增长中。可以采取两个手段: 
    第一:将数据库表拆分到不同的库中,比如 tblMEMBER 就可以拆分到 DB1 与 DB2 中去。 
    实际上,可以拆分到 DB001 ... DB100 甚至更多的库中间去。 
    DB1 与 DB2 最好不在一块硬盘上。 
    第二:如果更大量级的数据,则最好拆分到不同的数据库服务器中去。 

    数据库的拆分带来的是查询等操作的复杂性。简单地可以通过 hash 或者 按序号 匹配不同的数据库。复杂一些,应该设置一个独立的应用服务器(软件)协调其中的操作。 

    (2)中等量级数据库的优化技巧 

    所谓中等量级数据库是指数据库100万-500万条记录左右(单个数据库表)。这样的数据库为了提高访问(响应)速度,可以将表拆分到更小的表。比如 tblMEMBER 可以拆分为 tblMEMBER_00 ... tblMEMBER_99 。 
    这样可以保证每个表的记录数不超过50万,那速度是"相当"快了。 

    (3)避免使用视图(viewport)与关联 

    视图viewport与关联都是为了程序员处理相对复杂的数据管理提供方便的手段。万物有其利,必有其弊。视图和关联提高了编程效率,都会较大地影响数据库的访问效率(事实上并不像一般资料说介绍的的那样高效),因此如果是web应用,则建议一般不要使用视图与关联。 

    (4)不要忘记索引(index)也不要滥用索引(index) 

    索引是提高数据库效率的简单又高效的方法。只要是设置了数据库表(table),就不要忘记设置索引(index)。将索引设置在经常用于排序的字段上,其他字段就不要设置了。 
    索引不是越多越好,也不是什么字段都适合建立索引的。数据重复性太多的字段不要设置索引。比如 tblMEMBER 的 iSex 字段只有 0 1 两个值,就不要设置索引。 

    (5)二进制的 text image 等字段应该单独设置别的表中 

    一般的数据库应用难免都需要保存比如描述、图片等信息;一般描述类信息用 text 字段,图片类信息用 image 字段;这里要说的是,不要将这些字段与其他字段放在一个表中。 
    比如: 

    1. tblMEMBER  
    2. id (int)  
    3. cName (varchar)(64)  
    4. cDescription (text)  
    5. bPhoto (image)  
    6. dDate (datetime)  
    7. 就应该拆分为3个表  
    8. tblMEMBER  
    9. id (int)  
    10. cName (varchar)(64)  
    11. dDate (datetime)  
    12. tblMEMBER_DESC  
    13. id (int)  
    14. cDescription (text)  
    15. dDate (datetime)  
    16. tblMEMBER_PHOTO  
    17. id (int)  
    18. bPhoto (image)  
    19. dDate (datetime)  

    (6)不要使用文本类型的 id 

    一般的数据库表都会以一个种子字段作为主键。可以在与不少年青的程序员朋友沟通过程中,发现他们很喜欢用字符串类型的作为系统的 id 号。 
    比如:id = XX XX XX XX 这样的字符串,每两个位置代表不同的类别等含义。 
    不知道是那本教材如此误人子弟,作出这样的表率 :< 
    作为系统的 id 号,一定要使用数字型的。 

    (7)数据库表table的字段field不要太多 

    本以为无需说明,也是发现不少的朋友,为了省事,一股脑把所有的相关字段都放在一个表中间。这样做的后果便是,程序写起来简单了,运行效率下来了。 
    无论字段多少,有两类字段是必须独立出去的:一是进程更新的字段,比如文章的点击次数字段iShow,二是二进制或者是text字段; 

    (8)将字符串(varchar)比较变成数字型(int)比较 

    每个系统都会有用户管理,其中必然有 昵称,密码,邮件等的字符串类型数据比较的问题。在数据库操作中,字符串比较的效率是相当低下的。因此遇到字符串的比较,必须将其转换为数字型比较。 
    具体做法是:在数据库表中增加相应的数字字段,比如 cNickname -> iNickNumber ,其中 iNickNumber 的数值为 cNickname 的 哈希值(如何计算字符串的哈希值?请参阅本站的其他文章)。 
    通过这样的转换,系统效率可以提高 100 倍哦!!! 

    (9)为每个数据库表(table)设置 datetime 字段 

    在许多情况下,很多的表是不需要 datetime 字段用于保存时间的。本文的建议是你应该为每个表都设置 datetime 字段,而且默认值为 getdate()。 
    我们的经验是,datetime 是实数,占用字节不多;在进行系统维护,远程备份等环节都会发挥意想不到的效果。 

    (10)适当使用存储过程(Stored Processing) 

    存储过程(sp)已经被大大地宣传了,本文也不例外地赞许采用存储过程。本文的建议是只在下列情况才使用存储过程:一是一个业务处理是事务,包含了多个处理过程;二是一种处理被高频使用,使用存储过程可以提高效率; 

    (11)使用高效的分页(ination)技术 

    数据库记录分页列表是大量必须使用的基本技术,因此本文建议你在每个数据库中建立下面的存储过程: 

    1. CREATE PROCEDURE xsp_ination  
    2. (  
    3. @tblName   varchar(64),                  
    4. @strGetFields varchar(256) = "*",   
    5. @fldName varchar(64)="",                  
    6. @PageSize   int = 20,                     
    7. @PageIndex  int = 1,                          
    8. @OrderType bit = 1,                       
    9. @strWhere  varchar(256) = ""      
    10. )  
    11. AS   
    12. BEGIN  
    13. declare @strSQL   varchar(1000)     
    14. declare @strTmp   varchar(110)       
    15. declare @strOrder varchar(400)     
    16. SET NOCOUNT ON  
    17. if @OrderType != 0  
    18.     begin  
    19.         set @strTmp = "<(select min"   
    20.         set @strOrder = " order by [" + @fldName +"] desc"   
    21.     end  
    22. else   
    23.     begin   
    24.         set @strTmp = ">(select max"   
    25.         set @strOrder = " order by [" + @fldName +"] asc"   
    26.     end   
    27. if @PageIndex = 1  
    28.     begin  
    29.         if @strWhere != ""     
    30.             set @strSQL = "select top " + str(@PageSize) +" "+@strGetFields+ "  from " + @tblName + " where " + @strWhere + " " + @strOrder  
    31.         else   
    32.             set @strSQL = "select top " + str(@PageSize) +" "+@strGetFields+ "  from "+ @tblName + " "+ @strOrder  
    33.     end  
    34. else   
    35.     begin  
    36.         set @strSQL = "select top " + str(@PageSize) +" "+@strGetFields+ "  from "  
    37.                             + @tblName + " where [" + @fldName + "]" + @strTmp + "(["+ @fldName + "]) from (select top " + str((@PageIndex-1)*@PageSize) + " ["+ @fldName + "] from " + @tblName + " " + @strOrder + ") as tblTmp)"+ @strOrder  
    38.         if @strWhere != ""   
    39.             set @strSQL = "select top " + str(@PageSize) +" "+@strGetFields+ "  from "  
    40.                             + @tblName + " where [" + @fldName + "]" + @strTmp + "(["  
    41.                             + @fldName + "]) from (select top " + str((@PageIndex-1)*@PageSize) + " ["   
    42.                             + @fldName + "] from " + @tblName + " where " + @strWhere + " "  
    43.                             + @strOrder + ") as tblTmp) and " + @strWhere + " " + @strOrder   
    44.     end  
    45. EXEC (@strSQL)  
    46. if @@error=0 return 1  
    47. SET NOCOUNT OFF  
    48. END  
    49. GO  


    使用方法是(C#): 

    1. sql = "EXEC [dbo].[xsp_ination] \"tblNEWS\",\"*\",\"id\",40," + pindex.ToString() + ",1,\"iType=" + type.ToString();  
    2. SqlDataReader sr = ExecuteReader(sql);  
    3. while (sr.Read())  
    4. {  
    5.    ...  
    6. }  
    7. sr.Close();  


    上面的优化技巧仅是一些常见的手段,如果你的系统(小系统就算了)遇到效率问题,可以与联高软件联系。 

     

    来源:http://www.legalsoft.com.cn/docs/968.html

     

     

    =============================================================

    本文首先讨论了基于第三范式的数据库表的基本设计,着重论述了建立主键和索引的策略和方案,然后从数据库表的扩展设计和库表对象的放置等角度概述了数据库管理系统的优化方案。 

    关键词: 优化(Optimizing) 第三范式(3NF) 冗余数据(Redundant Data) 索引(Index) 数据分割(Data Partitioning) 对象放置(Object Placement) 

    1 引言 

    数 据库优化的目标无非是避免磁盘I/O瓶颈、减少CPU利用率和减少资源竞争。为了便于读者阅读和理解,笔者参阅了Sybase、Informix和 Oracle等大型数据库系统参考资料,基于多年的工程实践经验,从基本表设计、扩展设计和数据库表对象放置等角度进行讨论,着重讨论了如何避免磁盘 I/O瓶颈和减少资源竞争,相信读者会一目了然。 

    2 基于第三范式的基本表设计 

    在基于表驱动的信息管理系统(MIS)中,基本表的 设计规范是第三范式(3NF)。第三范式的基本特征是非主键属性只依赖于主键属性。基于第三范式的数据库表设计具有很多优点:一是消除了冗余数据,节省了 磁盘存储空间;二是有良好的数据完整性限制,即基于主外键的参照完整限制和基于主键的实体完整性限制,这使得数据容易维护,也容易移植和更新;三是数据的 可逆性好,在做连接(Join)查询或者合并表时不遗漏、也不重复;四是因消除了冗余数据(冗余列),在查询(Select)时每个数据页存的数据行就 多,这样就有效地减少了逻辑I/O,每个Cash存的页面就多,也减少物理I/O;五是对大多数事务(Transaction)而言,运行性能好;六是物 理设计(Physical Design)的机动性较大,能满足日益增长的用户需求。 

    在基本表设计中,表的主键、外键、索引设计占有非常重要的地位,但系统设计人员往往只注重于满足用户要求,而没有从系统优化的高度来认识和重视它们。实际上,它们与系统的运行性能密切相关。现在从系统数据库优化角度讨论这些基本概念及其重要意义: 

     

    (1) 主键(Primary Key):主键被用于复杂的SQL语句时,频繁地在数据访问中被用到。一个表只有一个主键。主键应该有固定值(不能为Null或缺省值,要有相对稳定 性),不含代码信息,易访问。把常用(众所周知)的列作为主键才有意义。短主键最佳(小于25bytes),主键的长短影响索引的大小,索引的大小影响索 引页的大小,从而影响磁盘I/O。主键分为自然主键和人为主键。自然主键由实体的属性构成,自然主键可以是复合性的,在形成复合主键时,主键列不能太多, 复合主键使得Join*作复杂化、也增加了外键表的大小。人为主键是,在没有合适的自然属性键、或自然属性复杂或灵敏度高时,人为形成的。人为主键一般是 整型值(满足最小化要求),没有实际意义,也略微增加了表的大小;但减少了把它作为外键的表的大小。 

     

    (2)外键(Foreign Key):外键的作用是建立关系型数据库中表之间的关系(参照完整性),主键只能从独立的实体迁移到非独立的实体,成为后者的一个属性,被称为外键。 

     

    (3) 索引(Index):利用索引优化系统性能是显而易见的,对所有常用于查询中的Where子句的列和所有用于排序的列创建索引,可以避免整表扫描或访问, 在不改变表的物理结构的情况下,直接访问特定的数据列,这样减少数据存取时间;利用索引可以优化或排除耗时的分类*作;把数据分散到不同的页面上,就分散 了插入的数据;主键自动建立了唯一索引,因此唯一索引也能确保数据的唯一性(即实体完整性);索引码越小,定位就越直接;新建的索引效能最好,因此定期更 新索引非常必要。索引也有代价:有空间开销,建立它也要花费时间,在进行Insert、Delete和Update*作时,也有维护代价。索引有两种:聚 族索引和非聚族索引。一个表只能有一个聚族索引,可有多个非聚族索引。使用聚族索引查询数据要比使用非聚族索引快。在建索引前,应利用数据库系统函数估算 索引的大小。 

    ① 聚族索引(Clustered Index):聚族索引的数据页按物理有序储存,占用空间小。选择策略是,被用于Where子句的列:包括范围查询、模糊查询或高度重复的列(连续磁盘扫 描);被用于连接Join*作的列;被用于Order by和Group by子句的列。聚族索引不利于插入*作,另外没有必要用主键建聚族索引。 

    ② 非聚族索引(Nonclustered Index):与聚族索引相比,占用空间大,而且效率低。选择策略是,被用于Where子句的列:包括范围查询、模糊查询(在没有聚族索引时)、主键或外 键列、点(指针类)或小范围(返回的结果域小于整表数据的20%)查询;被用于连接Join*作的列、主键列(范围查询);被用于Order by和Group by子句的列;需要被覆盖的列。对只读表建多个非聚族索引有利。索引也有其弊端,一是创建索引要耗费时间,二是索引要占有大量磁盘空间,三是增加了维护代 价(在修改带索引的数据列时索引会减缓修改速度)。那么,在哪种情况下不建索引呢?对于小表(数据小于5页)、小到中表(不直接访问单行数据或结果集不用 排序)、单值域(返回值密集)、索引列值太长(大于20bitys)、容易变化的列、高度重复的列、Null值列,对没有被用于Where子语句和 Join查询的列都不能建索引。另外,对主要用于数据录入的,尽可能少建索引。当然,也要防止建立无效索引,当Where语句中多于5个条件时,维护索引 的开销大于索引的效益,这时,建立临时表存储有关数据更有效。 

    批量导入数据时的注意事项:在实际应用中,大批量的计算(如电信话单计费)用C 语言程序做,这种基于主外键关系数据计算而得的批量数据(文本文件),可利用系统的自身功能函数(如Sybase的BCP命令)快速批量导入,在导入数据 库表时,可先删除相应库表的索引,这有利于加快导入速度,减少导入时间。在导入后再重建索引以便优化查询。 

     

    (4)锁:锁是并行处理的重要机 制,能保持数据并发的一致性,即按事务进行处理;系统利用锁,保证数据完整性。因此,我们避免不了死锁,但在设计时可以充分考虑如何避免长事务,减少排它 锁时间,减少在事务中与用户的交互,杜绝让用户控制事务的长短;要避免批量数据同时执行,尤其是耗时并用到相同的数据表。锁的征用:一个表同时只能有一个 排它锁,一个用户用时,其它用户在等待。若用户数增加,则Server的性能下降,出现“假死”现象。如何避免死锁呢?从页级锁到行级锁,减少了锁征用; 给小表增加无效记录,从页级锁到行级锁没有影响,若在同一页内竞争有影响,可选择合适的聚族索引把数据分配到不同的页面;创建冗余表;保持事务简短;同一 批处理应该没有网络交互。 

     

    (5)查询优化规则:在访问数据库表的数据(Access Data)时,要尽可能避免排序(Sort)、连接(Join)和相关子查询*作。经验告诉我们,在优化查询时,必须做到: 

    ① 尽可能少的行; 

    ② 避免排序或为尽可能少的行排序,若要做大量数据排序,最好将相关数据放在临时表中*作;用简单的键(列)排序,如整型或短字符串排序; 

    ③ 避免表内的相关子查询; 

    ④ 避免在Where子句中使用复杂的表达式或非起始的子字符串、用长字符串连接; 

    ⑤ 在Where子句中多使用“与”(And)连接,少使用“或”(Or)连接; 

    ⑥ 利用临时数据库。在查询多表、有多个连接、查询复杂、数据要过滤时,可以建临时表(索引)以减少I/O。但缺点是增加了空间开销。 

    除非每个列都有索引支持,否则在有连接的查询时分别找出两个动态索引,放在工作表中重新排序。 

     

    3 基本表扩展设计 

    基 于第三范式设计的库表虽然有其优越性(见本文第一部分),然而在实际应用中有时不利于系统运行性能的优化:如需要部分数据时而要扫描整表,许多过程同时竞 争同一数据,反复用相同行计算相同的结果,过程从多表获取数据时引发大量的连接*作,当数据来源于多表时的连接*作;这都消耗了磁盘I/O和CPU时间。 

    尤其在遇到下列情形时,我们要对基本表进行扩展设计:许多过程要频繁访问一个表、子集数据访问、重复计算和冗余数据,有时用户要求一些过程优先或低的响应时间。 

    如何避免这些不利因素呢?根据访问的频繁程度对相关表进行分割处理、存储冗余数据、存储衍生列、合并相关表处理,这些都是克服这些不利因素和优化系统运行的有效途径。 

     

    3.1 分割表或储存冗余数据 

    分割表分为水平分割表和垂直分割表两种。分割表增加了维护数据完整性的代价。 

    水 平分割表:一种是当多个过程频繁访问数据表的不同行时,水平分割表,并消除新表中的冗余数据列;若个别过程要访问整个数据,则要用连接*作,这也无妨分割 表;典型案例是电信话单按月分割存放。另一种是当主要过程要重复访问部分行时,最好将被重复访问的这些行单独形成子集表(冗余储存),这在不考虑磁盘空间 开销时显得十分重要;但在分割表以后,增加了维护难度,要用触发器立即更新、或存储过程或应用代码批量更新,这也会增加额外的磁盘I/O开销。 

    垂 直分割表(不破坏第三范式),一种是当多个过程频繁访问表的不同列时,可将表垂直分成几个表,减少磁盘I/O(每行的数据列少,每页存的数据行就多,相应 占用的页就少),更新时不必考虑锁,没有冗余数据。缺点是要在插入或删除数据时要考虑数据的完整性,用存储过程维护。另一种是当主要过程反复访问部分列 时,最好将这部分被频繁访问的列数据单独存为一个子集表(冗余储存),这在不考虑磁盘空间开销时显得十分重要;但这增加了重叠列的维护难度,要用触发器立 即更新、或存储过程或应用代码批量更新,这也会增加额外的磁盘I/O开销。垂直分割表可以达到最大化利用Cache的目的。 

    总之,为主要过程分割表的方法适用于:各个过程需要表的不联结的子集,各个过程需要表的子集,访问频率高的主要过程不需要整表。在主要的、频繁访问的主表需要表的子集而其它主要频繁访问的过程需要整表时则产生冗余子集表。 

    注意,在分割表以后,要考虑重新建立索引。 

     

    3.2 存储衍生数据 

    对一些要做大量重复性计算的过程而言,若重复计算过程得到的结果相同(源列数据稳定,因此计算结果也不变),或计算牵扯多行数据需额外的磁盘I/O开销,或计算复杂需要大量的CPU时间,就考虑存储计算结果(冗余储存)。现予以分类说明: 

    若在一行内重复计算,就在表内增加列存储结果。但若参与计算的列被更新时,必须要用触发器更新这个新列。 

    若对表按类进行重复计算,就增加新表(一般而言,存放类和结果两列就可以了)存储相关结果。但若参与计算的列被更新时,就必须要用触发器立即更新、或存储过程或应用代码批量更新这个新表。 

    若对多行进行重复性计算(如排名次),就在表内增加列存储结果。但若参与计算的列被更新时,必须要用触发器或存储过程更新这个新列。 

    总之,存储冗余数据有利于加快访问速度;但违反了第三范式,这会增加维护数据完整性的代价,必须用触发器立即更新、或存储过程或应用代码批量更新,以维护数据的完整性。 

     

    3.3 消除昂贵结合 

    对 于频繁同时访问多表的一些主要过程,考虑在主表内存储冗余数据,即存储冗余列或衍生列(它不依赖于主键),但破坏了第三范式,也增加了维护难度。在源表的 相关列发生变化时,必须要用触发器或存储过程更新这个冗余列。当主要过程总同时访问两个表时可以合并表,这样可以减少磁盘I/O*作,但破坏了第三范式, 也增加了维护难度。对父子表和1:1关系表合并方法不同:合并父子表后,产生冗余表;合并1:1关系表后,在表内产生冗余数据。 

     

    4 数据库对象的放置策略 

    数据库对象的放置策略是均匀地把数据分布在系统的磁盘中,平衡I/O访问,避免I/O瓶颈。 

    ⑴ 访问分散到不同的磁盘,即使用户数据尽可能跨越多个设备,多个I/O运转,避免I/O竞争,克服访问瓶颈;分别放置随机访问和连续访问数据。 

    ⑵ 分离系统数据库I/O和应用数据库I/O。把系统审计表和临时库表放在不忙的磁盘上。 

    ⑶ 把事务日志放在单独的磁盘上,减少磁盘I/O开销,这还有利于在障碍后恢复,提高了系统的安全性。 

    ⑷ 把频繁访问的“活性”表放在不同的磁盘上;把频繁用的表、频繁做Join*作的表分别放在单独的磁盘上,甚至把把频繁访问的表的字段放在不同的磁盘上,把访问分散到不同的磁盘上,避免I/O争夺; 

    ⑸ 利用段分离频繁访问的表及其索引(非聚族的)、分离文本和图像数据。段的目的是平衡I/O,避免瓶颈,增加吞吐量,实现并行扫描,提高并发度,最大化磁盘 的吞吐量。利用逻辑段功能,分别放置“活性”表及其非聚族索引以平衡I/O。当然最好利用系统的默认段。另外,利用段可以使备份和恢复数据更加灵活,使系 统授权更加灵活。

    参考资料:http://www.xiaotianya.com/read-7-2026-1.html

    来源:http://www.cnblogs.com/shenpeng1024/archive/2008/03/17/1110642.html


    转载自:http://uule.iteye.com/blog/1499871

    展开全文
  • Django最为全面的数据库优化手段

    千次阅读 2019-09-12 15:26:03
    数据库访问优化 Django的数据库层提供了很多方法来帮助开发者充分的利用他们的数据库。这篇文档收集了相关文档的一些链接,添加了大量提示,并且按照优化数据库使用的步骤的概要来组织。 性能优先 作为通用的编程...

    数据库访问优化

    Django的数据库层提供了很多方法来帮助开发者充分的利用他们的数据库。这篇文档收集了相关文档的一些链接,添加了大量提示,并且按照优化数据库使用的步骤的概要来组织。

    性能优先

    作为通用的编程实践,性能的重要性不用多说。弄清楚你在执行什么查询以及你的开销花在哪里。你也可能想使用外部的项目,像django-debug-toolbar,或者直接监控数据库的工具。

    记住你可以优化速度、内存占用,甚至二者一起,这取决于你的需求。一些针对其中一个的优化会对另一个不利,但有时会对二者都有帮助。另外,数据库进程做的工作,可能和你在Python代码中做的相同工作不具有相同的开销。决定你的优先级是什么,是你自己的事情,你必须要权衡利弊,按需使用它们,因为这取决于你的应用和服务器。

    对于下面提到的任何事情,要记住在任何修改后验证一下,确保修改是有利的,并且足够有利,能超过你代码中可读性的下降。下面的所有建议都带有警告,在你的环境中大体原则可能并不适用,或者会起到相反的效果。

    使用标准数据库优化技巧

    ...包括:

    索引。在你决定哪些索引应该添加 之后,这一条具有最高优先级。使用Field.db_index或者Meta.index_together在Dhango中添加它们。考虑在你经常使用filter()、exclude()、order_by()和其它方法查询的字段上面添加索引,因为索引有助于加速查找。注意,设计最好的索引方案是一个复杂的、数据库相关的话题,它取决于你应用的细节。持有索引的副作用可能会超过查询速度上的任何收益。

    合理使用字段类型。

    我们假设你已经完成了上面这些显而易见的事情。这篇文档剩下的部分,着重于讲解如何以不做无用功的方式使用Django。这篇文档也没有强调用在开销大的操作上其它的优化技巧,像general purpose caching。

    理解查询集

    理解查询集(QuerySets) 是通过简单的代码获取较好性能至关重要的一步。特别是:

    理解查询集计算

    要避免性能问题,理解以下几点非常重要:

    QuerySets是延迟的。

    什么时候它们被计算出来。

    数据在内存中如何存储。

    理解缓存属性

    和整个QuerySet的缓存相同,ORM对象的属性的结果中也存在缓存。通常来说,不可调用的属性会被缓存。例如下面的博客模型示例:

    >>> entry = Entry.objects.get(id=1)
    >>> entry.blog   # Blog object is retrieved at this point
    >>> entry.blog   # cached version, no DB access
    

    但是通常来讲,可调用的属性每一次都会访问数据库。

    >>> entry = Entry.objects.get(id=1)
    >>> entry.authors.all()   # query performed
    >>> entry.authors.all()   # query performed again
    

    要小心当你阅读模板代码的时候 —— 模板系统不允许使用圆括号,但是会自动调用callable对象,会隐藏上述区别。

    要小心使用你自定义的属性 —— 实现所需的缓存取决于你,例如使用cached_property装饰符。

    使用with模板标签

    要利用QuerySet的缓存行为,你或许需要使用with模板标签。

    使用iterator()

    当你有很多对象时,QuerySet的缓存行为会占用大量的内存。这种情况下,采用iterator()解决。

    在数据库中而不是Python中做数据库的工作

    比如:

    在最基础的层面上,使用过滤器和反向过滤器对数据库进行过滤。

    使用F 表达式在相同模型中基于其他字段进行过滤。

    使用数据库中的注解和聚合。

    如果上面那些都不够用,你可以自己生成SQL语句:

    使用QuerySet.extra()

    extra()是一个移植性更差,但是功能更强的方法,它允许一些SQL语句显式添加到查询中。如果这些还不够强大:

    使用原始的SQL

    编写你自己的自定义SQL语句,来获取数据或者填充模型。使用django.db.connection.queries来了解Django为你编写了什么,以及从这里开始。

    用唯一的被或索引的列来检索独立对象

    有两个原因在get()中,用带有unique或者db_index的列检索独立对象。首先,由于查询经过了数据库的索引,所以会更快。其次,如果很多对象匹配查询,查询会更慢一些;列上的唯一性约束确保这种情况永远不会发生。

    所以,使用博客模型的例子:

    >>> entry = Entry.objects.get(id=10)
    

    会快于:

    >>> entry = Entry.object.get(headline="News Item Title")
    

    因为id被数据库索引,而且是唯一的。

    下面这样做会十分缓慢:

    >>> entry = Entry.objects.get(headline__startswith="News")
    

    首先, headline没有被索引,它会使查询变得很慢:

    其次,这次查找并不确保返回唯一的对象。如果查询匹配到多于一个对象,它会在数据库中遍历和检索所有这些对象。如果记录中返回了成百上千个对象,代价是非常大的。如果数据库运行在分布式服务器上,网络开销和延迟也是一大因素,代价会是它们的组合。

    一次性检索你需要的任何东西

    在不同的位置多次访问数据库,一次获取一个数据集,通常来说不如在一次查询中获取它们更高效。如果你在一个循环中执行查询,这尤其重要。有可能你会做很多次数据库查询,但只需要一次就够了。所以:

    使用QuerySet.select_related()和prefetch_related()

    充分了解并使用select_related()和prefetch_related():

    在视图的代码中,

    以及在适当的管理器和默认管理器中。要意识到你的管理器什么时候被使用和不被使用;有时这很复杂,所以不要有任何假设。

    不要获取你不需要的东西 使用QuerySet.values()和values_list()

    当你仅仅想要一个带有值的字典或者列表,并不需要使用ORM模型对象时,可以适当使用values()。对于在模板代码中替换模型对象,这样会非常有用 —— 只要字典中带有的属性和模板中使用的一致,就没问题。

    使用QuerySet.defer()和only()

    如果一些数据库的列你并不需要(或者大多数情况下并不需要),使用defer()和only()来避免加载它们。注意如果你确实要用到它们,ORM会在另外的查询之中获取它们。如果你不能够合理地使用这些函数,不如不用。

    另外,当建立起一个带有延迟字段的模型时,要意识到一些(小的、额外的)消耗会在Django内部产生。不要不分析数据库就盲目使用延迟字段,因为数据库必须从磁盘中读取大多数非text和VARCHAR数据,在结果中作为单独的一行,即使其中的列很少。 defer()和only()方法在你可以避免加载大量文本数据,或者可能要花大量时间处理而返回给Python的字段时,特别有帮助。像往常一样,应该先写出个大概,之后再优化。

    使用QuerySet.count()

    ...如果你想要获取大小,不要使用 len(queryset)。

    使用QuerySet.exists()

    ...如果你想要知道是否存在至少一个结果,不要使用if queryset。

    但是:

    不要过度使用 count() 和 exists()

    如果你需要查询集中的其他数据,就把它加载出来。

    例如,假设Email模型有一个body属性,并且和User有多对多的关联,下面的的模板代码是最优的:

    {% if display_inbox %}
      {% with emails=user.emails.all %}
        {% if emails %}
          <p>You have {{ emails|length }} email(s)</p>
          {% for email in emails %}
            <p>{{ email.body }}</p>
          {% endfor %}
        {% else %}
          <p>No messages today.</p>
        {% endif %}
      {% endwith %}
    {% endif %}
    

    这是因为:

    因为查询集是延迟加载的,如果‘display_inbox’为False,不会查询数据库。

    使用with意味着我们为了以后的使用,把user.emails.all储存在一个变量中,允许它的缓存被复用。

    {% if emails %}的那一行调用了QuerySet.bool(),它导致user.emails.all()查询在数据库上执行,并且至少在第一行以一个ORM对象的形式返回。如果没有任何结果,会返回False,反之为True。

    {{ emails|length }}调用了QuerySet.len()方法,填充了缓存的剩余部分,而且并没有执行另一次查询。

    for循环的迭代器访问了已经缓存的数据。

    总之,这段代码做了零或一次查询。唯一一个慎重的优化就是with标签的使用。在任何位置使用QuerySet.exists()或者QuerySet.count()都会导致额外的查询。

    使用QuerySet.update()和delete()

    通过QuerySet.update()使用批量的SQL UPDATE语句,而不是获取大量对象,设置一些值再单独保存。与此相似,在可能的地方使用批量deletes。

    但是要注意,这些批量的更新方法不会在单独的实例上面调用save()或者delete()方法,意思是任何你向这些方法添加的自定义行为都不会被执行,包括由普通数据库对象的信号驱动的任何方法。

    直接使用外键的值

    如果你仅仅需要外键当中的一个值,要使用对象上你已经取得的外键的值,而不是获取整个关联对象再得到它的主键。例如,执行:

    entry.blog_id
    

    而不是:

    entry.blog.id
    

    不要做无谓的排序

    排序并不是没有代价的;每个需要排序的字段都是数据库必须执行的操作。如果一个模型具有默认的顺序(Meta.ordering),并且你并不需要它,通过在查询集上无参调用order_by() 来移除它。

    向你的数据库添加索引可能有助于提升排序性能。

    整体插入

    创建对象时,尽可能使用bulk_create()来减少SQL查询的数量。例如:

    Entry.objects.bulk_create([
        Entry(headline="Python 3.0 Released"),
        Entry(headline="Python 3.1 Planned")
    ])
    

    ...更优于:

    Entry.objects.create(headline="Python 3.0 Released")
    Entry.objects.create(headline="Python 3.1 Planned")
    

    注意该方法有很多注意事项,所以确保它适用于你的情况。

    这也可以用在ManyToManyFields中,所以:

    my_band.members.add(me, my_friend)
    

    ...更优于:

    my_band.members.add(me)
    my_band.members.add(my_friend)
    

    ...其中Bands和Artists具有多对多关联。

    展开全文
  • MySql数据库优化

    2019-11-16 12:06:03
    文章目录MySql数据库优化——史上最全导语1,数据库优化手段2,数据库优化必须了解的知识2.1 慢查询2.2 执行计划3,索引优化3.1 关于索引3.2 索引应用场景4,查询缓存5,sql优化 导语 在日常开发中,我们的数据往往...

    MySql数据库优化

    导语

    在日常开发中,我们的数据往往存储在数据库中,但是由于数据库本身是持久化存储,数据的查询速度受到磁盘IO瓶颈的限制,同时,随着数据量的增长,数据的查询也会因为单表数据量的巨大,影响查询速度。所以我们需要对数据库进行优化,提高系统的响应效率。

    1,数据库优化手段

    1. 索引优化。

    2. 添加查询缓存。

    3. 优化数据库SQL语句。

    2,数据库优化必须了解的知识

    2.1 慢查询

    1,查看慢查询的状态
    	show variables like '%quer%'
    2,开启慢查询
    	set global log_slow_queries = on;
    3,修改慢查询最短时间为1秒
    	set global long_query_time = 1;
    4,查看MySQL执行过的慢查询SQL语句
    	show variables like '%quer%';
    

    在这里插入图片描述

    2.2 执行计划

    数据库查询优化中需要了解MySQL执行计划命令,查看sql的执行效率。
    在这里插入图片描述

    3,索引优化

    3.1 关于索引

    • 作用

    加快以索引字段为条件的查询效率。

    • 创建索引的语法
    create index 索引名字 on 表(字段);
    
    • 删除索引
    drop index 索引名字;
    
    • 查询某张表中创建了哪些索引
    show index from 表名;
    
    • 索引特点

    ①索引会占用存储空间,比较少。

    ②MySQL会自动为primary 列和unique 列自动增加索引。

    ③MySQL数据库对数据做DML操作时,需要同时做维护索引的操作。

    隐含之意,就是索引会降低数据库增删改的效率。

    • 使用原则

    一般会对sql中的where条件字段或者order by字段建立索引。

    3.2 索引应用场景

    实际项目中,如果从业务角度出发,发现经常会用到某个字段,对表数据进行查询,或者根据经常用到某个字段的排序,则该数据是需要增加索引的。

    4,查询缓存

    在数据库操作对象DAO处增加查询缓存。

    参考Ehcache缓存,或者MyBatis+Ehcache整合方案、Hibernate二级缓存Ehcache

    需要注意的问题是,要注意数据的一致性,所以缓存思路如下:

    1,只对查询结果进行缓存。

    2,缓存结果存放要以业务逻辑相关为划分单位。比如,如果是单表,则可以创建一个缓存区域,与该表对应,如果业务中涉及到表连接操作,要将查询结果缓存在这多张表的查询结果都要缓存在对应的一个缓存区域中。

    当执行增删改的时候,为了避免出现脏数据。

    基于以上的特点,缓存原则是对那些查询需求远大于增删改需求的数据,进行缓存。例如:新闻网站的首页数据、电商的类别数据等。

    5,sql优化

    这一部分查看我的博客:SQL优化

    展开全文
  • mysql数据库优化

    2018-01-13 23:49:58
    2.数据库优化手段 创建索引:创建合适的索引,我们就可以先在索引中查询,查询以后直接找对应的记录 分表:当一张表的数据比较多或者一张表的某些字段的值比较多并且很少使用时,采用水平分表或者垂直分表来优化 ...

    mysql数据库性能优化

     

    个人博客网站:http://01time.cn

    mysql数据库的优化,其他数据库类似

    1.数据库优化之定位

    查找定位慢查询

    2.数据库优化手段

    • 创建索引:创建合适的索引,我们就可以先在索引中查询,查询以后直接找对应的记录
    • 分表:当一张表的数据比较多或者一张表的某些字段的值比较多并且很少使用时,采用水平分表或者垂直分表来优化
    • 读写分离:当一台服务器不能满足需求时,采用读写分离的方式进行集群
    • 缓存:采用redis来进行缓存

    3.数据库优化之定位慢查询的方式

    在项目自验项目转测试之前,在启动mysql数据库时开启慢查询,并且把执行慢查询的语句写到日志中,在

    运行一定时间后,通过查看日志找到慢查询语句

    开启慢查询方式一:修改配置文件

    Windows:Windows 的配置文件为 my.ini,一般在 MySQL 的安装目录下或者 c:\Windows 下。

    Linux:Linux 的配置文件为 my.cnf ,一般在 /etc 下

    在 my.ini 增加几行:

     

    long_query_time     :  设定慢查询的阀值,超出次设定值的SQL即被记录到慢查询日志,缺省值为10s
    slow_query_log      :  指定是否开启慢查询日志
    log_slow_queries    :  指定是否开启慢查询日志(该参数要被slow_query_log取代,做兼容性保留)
    slow_query_log_file :  指定慢日志文件存放位置,可以为空,系统会给一个缺省的文件host_name-slow.log
    min_examined_row_limit:查询检查返回少于该参数指定行的SQL不被记录到慢查询日志
    log_queries_not_using_indexes: 不使用索引的慢查询日志是否记录到索引

    4.数据库优化之分析慢查询

    使用explain慢查询语句,来详细分析慢查询语句

     

    mysql>explain select * from dept where loc='aaa' \G
    *********************1.row ********************
                   id:1                //查询序列号
    select_type:SIMPLE      //查询类型
              table:dept          //查询的表名
              type:ALL  所描的方式,all表示全表扫描这列很重要,显示了连接使用了哪                                             种类别,有无使用索引.
    从最好到最差的连接类型为const、eq_reg、ref、range、indexhe和ALL 
              possible_keys:NULL//可能使用到的索引
              key:NULL//实际使用到的索引
              key_len:NULL//
              rows:10//该sql语句扫描了多少行,可能得到的记录
              Extra:Using where //sql语句的额外信息,比如排序方式filesort

     

     

      5.数据库优化之遵循范式

       数据库表设计时需要遵循范式

      表的范式,是首先符合1NF,才能满足2NF,进一步满足3NF

    1NF:即表的列具有原子性不可再分解,即列的信息,不能分解,只要数据库是关系型数据库,就自动的满足1NF,关系型数据库中是不允许分割列的

    2NF:表中的记录是唯一的,通常我们设计一个主键来实现

    3NF:即表中不要有冗余的数据,就是说,表的信息,如果能够被推导出来,就不应该单独的设计一个字段来存放(外键)

    反3NF:没有冗余的数据库未必是最好的数据库,有时为了提高运行效率,就必须降低范式标准,适当的保留冗余数据,具体做法是:在概念数据库设计时遵循第三范式,降低范式标准的工作放到物理数据模型设计时考虑,降低范式就是增加字段,允许冗余,订单和订单项,相册浏览次数和照片的浏览次数等

    6.数据库优化之选择合适的存储引擎

    在开发中,我们经常使用的存储引擎myisam/innodb/memory

    MyISAM存储引擎

     如果表对事物要求不高,同时是以查询和添加为主的,我们考虑使用myisam存储引擎,比如bbs中的发帖表,回复表。

    INNODB存储引擎

    对事务要求高,保存的数据都是重要数据,我们建议使用INNODB存储引擎,比如订单表,账号表

    Memory存储引擎

    我们数据变化频繁,不需要入库,同时又频繁的查询和修改,我们考虑使用Memmory存储引擎,速度极快

    MyISAM存储引擎与INNODB存储引擎的主要区别:

    1.事务安全 myisam不支持事务而innodb支持

    2.查询和添加速度  myisam不用支持事务就不用考虑同步锁,查询和添加的速度快

    3.锁机制 myisam只支持表锁,innodb支持行锁

    4.外键 myisam不支持外键,innodb支持外键

    5.支持全文索引 myisam支持全文索引,innodb不支持全文索引

    7.数据库优化之创建合适的索引

    索引(Index)是帮助DBMS高效获取数据的数据结构

    分类:普通索引/唯一索引/主键索引/全文索引

    普通索引:允许重复的值出现

    唯一索引:除了不能有重复的值外,其他的和普通索引一样

    主键索引:是随着设定主键而创建的,也就是把某个列设为主键的时候,数据库就会给该列自动创建索引,这就是主键索引,唯一并且没有null值

    全文索引:用来对表中的文本域(char,varchar,text)进行索引,全文索引针对myisam

    8.数据库优化之索引使用小技巧

    索引弊端

    1.占用磁盘空间

    2.对dml(插入,修改,删除)操作有影响,变慢

    使用场景

    a:肯定在where条件经常使用,如果不做查询就没有意义

    b:该字段的内容不是唯一的几个值

    c:字段内容不是频繁变化,不会出现在where语句中字段不该创建索引

    具体技巧

    1.对于创建的多列索引(复合索引),不是使用的第一部分就不会使用索引

     

    alert table dept add index my_index(dname,loc);//dname左边的列,loc就是右边的列
    explain select * from dept where dname='aaa' \G会使用到索引
    explain select * from dept where loc='aaa' \G就不会使用到索引

     2.对于使用like查询,查询如果是'%aaa' 就不会使用到索引,而‘aaa%'会使用到索引

     

     

    explain select * from dept where dname like '%aaa' \G 不会使用到索引
    explain select * from dept wehre dname like 'aaa%' \G 会使用到索引

      所以在like查询时,关键字的最前面不能使用%或者_这样的字符,如果一定要前面有变化的值,则考虑使用全文索引->sphinx

     

    3.如果条件中有or,有条件没有使用索引,即使其中有条件带索引也不会使用,换言之,就是要求使用的所有字段,都必须单独使用时能使用索引

    4.如果列类型是字符串,那一定要在条件中将数据库使用引号引起来,否则不使用索引

    explain select * from dept where dname='111'//使用索引
    explain select * from dept where dname =111//不使用索引

    5.如果myslq估计使用全表扫描比使用索引快,则不用索引

    如:表里面只有一条记录

    9.数据库优化之分表

    分表分为水平(按行)分表和垂直(按列)分表

    水平分表:

    根据经验,mysql表数据一般达到百万级别,查询效率会很低,容易造成表锁,甚至堆积很多连接,直接挂掉;水平分表能够很大程度减少这些压力,按行数据进行分表

    垂直分表:

    如果一张表中某个字段非常多(长文本,二进制),而且只有在很少的情况下会查询,这时候就可以把字段多个单独放到一个表,通过外键关联起来。按列进行分表

    比如:考试详情表,一般我们只关注分数,不关注详情

    水平分表策略

    1.按时间分表

        这种分表方式有一定的局限性,当数据有较强的实效性,如微博发送记录,微信消息记录等,这种数据很少有用户会查询几个月前的数据,如就可以按月分表

    2.按区间范围分表

       一般在有严格的自增id需求上,如按照user_id 水平分表:

       table_1 user_id 从1~100w

       table_2 user_id 从101~200w

        table_3 user_id 从201~300w

    3.hash分表******(用的最多)

       通过一个原始目标的ID或者名称通过一定的hash算法计算出数据存储表的表名,然后访问相应的表

    10.数据库优化之读写分离

        当一台数据库支持的最大并发连接数是有限的,如果用户并发访问太多,一台服务器满足不了要求时,就可以集群群里,mysql的集群处理技术最常用的就是读写分离。

    1.主从同步

             数据库最终会把数据持久化到磁盘,如果集群必须确保每个数据库服务器的数据是一直的,能改变数据库的操作都往主数据库去写,而其他的数据库从主数据库上同步数据

    2.读写分离

    使用 负载均衡来实现写的操作都往主数据库去,而读的操作都往从服务器去

     

    11.数据库优化之缓存

          在持久层(dao)和数据(db)之间添加一个缓存层,如果用户访问的数据已经缓存起来时,在用户访问数据库直接从缓存中获取,不用访问数据库,而缓存是在内存级别的,访问速度快。

    作用:减少数据库服务器压力,减少访问时间。

    java中常用的缓存有reids,memcache

    可以使用redis作为中央缓存


     

    展开全文
  • 数据库通用优化手段

    2019-06-24 21:57:03
    1、翻页:取消深翻页,只能上一页和下一页,这样数据库不会频繁的交换内存和磁盘中的数据 2、大字段垂直拆分,使用别的表 3、大表水平拆分 4、大数据量表取消join操作,分多次查询 5、永远使用小结果集驱动大...
  • 数据库优化手段

    2010-07-20 15:10:00
    一般优化手段: <br /> 配置: 1、日志文件、索引数据文件和数据文件分磁盘放,提高IO效率 2、多CPU环境下的配置 Sybase:max online engine/min online engine,引擎数和具体...
  • 数据库优化方面

    2020-03-22 23:57:34
    数据库优化手段: 创建索引:创建合适的索引,我们就可以现在索引中查询,查询到以后直接找对应的记录。 分表:当一张表的数据比较多或者一张表的某些字段的值比较多并且很少使用时,采用水平分表和垂直分表来优化 ...
  • 数据库优化手段

    2017-07-19 10:33:00
    1.sql语句优化 (where条件位置的优化)  eg. select * from student where sex ='男' and department ='中文系';  替换为  select * from student where department = '中文系' and sex ='男';  (哪个...
  • 数据库优化

    2019-08-25 11:59:20
    数据库优化 优化基本手段 说明:计算机性能的瓶颈通常在于磁盘的IO 手段: 进行架构调整 进行硬件提升 减少磁盘的IO 优化SQL语句 数据库的设计 数据库的设计 存储引擎的选择 根据需要选择合适的存储引擎,见...
  • 数据库优化详解

    2020-12-14 18:06:50
    可以看出来,数据结构、SQL、索引是成本最低,且效果最好的优化手段数据库优化从以下几个方面优化: 数据库设计—三大范式、字段、表结构 数据库索引 存储过程 (模块化编程,可以提高速度) 分表分库 (水平分割,...
  • 2. 数据库主从数据库, 主数据库负责所有的更新操作, 从数据库负责读取操作; 3. 数据量大的情况下, 考虑对数据库进行拆分(垂直分区),将那些没有关联的模块进行拆分; 4. 当单表数据量大, 需要考虑进行...
  • 数据库优化方案整理

    万次阅读 多人点赞 2018-08-29 16:05:16
    一:优化说明 A:有数据表明,用户可以承受的最大等待时间为8秒。...可以看出来,数据结构、SQL、索引是成本最低,且效果最好的优化手段。 C:性能优化是无止境的,当性能可以满足需求时即可,不要过度优化...
  • 数据库优化方案

    2019-01-09 15:35:58
    数据库优化方案整理(转) 一:优化说明 A:有数据表明,用户可以承受的最大等待时间...可以看出来,数据结构、SQL、索引是成本最低,且效果最好的优化手段。 C:性能优化是无止境的,当性能可以满足需求时即可,不要...
  • 数据库优化整理

    2019-08-22 20:10:53
    一:优化说明 A:有数据表明,用户可以承受的最大等待时间为8秒。...可以看出来,数据结构、SQL、索引是成本最低,且效果最好的优化手段。 C:性能优化是无止境的,当性能可以满足需求时即可,不要过度优化...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,646
精华内容 658
关键字:

数据库优化手段