数据库优化技巧

1.消除对大型表行数据的顺序存取

  在嵌套查询中,对表的顺序存取对查询效率可能产生致命的影响。比如采用顺序存取策略,一个嵌套3层的查询,如果每层都查询1000行,那么这个查询就要查询10亿行数据。避免这种情况的主要方法就是对连接的列进行索引。例如,两个表:订单表(订单号、名称、类型……)和花样表(花样号、订单号、交样时间...)。如果两个表要做连接,就要在“订单号”这个连接字段上建立索引。
还可以使用并集来避免顺序存取。尽管在所有的检查列上都有索引,但某些形式的where子句强迫优化器使用顺序存取。下面的查询将强迫对clr_writeback表执行顺序操作:
SELECT * FROM clr_writeback WHERE (ordid = 23 AND smpid > 20) OR smpid = 145
虽然在ordid和smpid上建有索引,但是在上面的语句中优化器还是使用顺序存取路径扫描整个表。因为这个语句要检索的是分离的行的集合,所以应该改为如下语句:
SELECT * FROM clr_writeback WHERE ordid = 23 AND smpid > 20
UNION
SELECT * FROM clr_writeback WHERE smpid = 145
这样就能利用索引路径处理查询。

  2.使用临时表加速查询

  把表的一个子集进行排序并创建临时表,有时能加速查询。它有助于避免多重排序操作,而且在其他方面还能简化优化器的工作。例如:
SELECT o.ordid , s.stt
FROM clr_order as o,clr_sample as s
WHERE o.id = s.ordid
AND s.stt>'0'
ORDER BY o.ordid
如果这个查询要被执行多次而不止一次,可以把所有未完成的花样找出来放在一个临时文件中,并订单名字进行排序:
SELECT o.ordid , s.stt
FROM clr_order as o,clr_sample as s
WHERE o.id = s.ordid
AND s.stt>'0'
ORDER BY o.ordid
INTO TEMP order_with_sample
然后以下面的方式在临时表中查询:
SELECT * FROM order_with_sample
WHERE stt>'0'
临时表中的行要比主表中的行少,而且物理顺序就是所要求的顺序,减少了磁盘I/O,所以查询工作量可以得到大幅减少。
注意:临时表创建后不会反映主表的修改。在主表中数据频繁修改的情况下,注意不要丢失数据。
   
  3.尽量少使用or使用union

  使用OR会引起全表搜索例:  
select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi='2004-9-16' or gid>9990000
用时:68秒。扫描计数 1,逻辑读 404008 次,物理读 283 次,预读 392163 次。

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
用时:9秒。扫描计数 8,逻辑读 67489 次,物理读 216 次,预读 7499 次。

 4.字段提取要按照“需多少、提多少”的原则,避免“select *”

  我们来做一个试验:
  select top 10000 gid,fariqi,reader,title from tgongwen order by gid desc
  用时:4673毫秒

  select top 10000 gid,fariqi,title from tgongwen order by gid desc
  用时:1376毫秒

  select top 10000 gid,fariqi from tgongwen order by gid desc
  用时:80毫秒
  由此看来,我们每少提取一个字段,数据的提取速度就会有相应的提升。提升的速度还要看您舍弃的字段的大小来判断。

  
  5..NET窗体优化

  默认的 Forms Designer(窗体设计器)生成的代码不能始终创建适用于创建 Microsoft? Windows? 窗体的最优代码。但是,执行一些操作可以帮助优化生成的代码。通过编写自己的窗体初始化代码,可以改进窗体的加载性能。
此外,通过重新排列和/或覆盖由 Microsoft Visual Studio? .NET 中的 Forms Designer(窗体设计器)生成的代码,可以显著提高应用程序整个窗体的加载性能。
警告:请勿在修改 InitializeComponent 后使用设计器。
InitializeComponent 方法前有一个注释,警告您不要修改代码。如果修改 InitializeComponent 方法中的代码,将无法再使用 Forms Designer(窗体设计器)。如果使用 Forms Designer(窗体设计器),所做的修改将丢失。只应在开发的最后阶段,完成所有设计工作后,再执行这些优化。


  *减少方法调用的数目

  提高窗体加载性能的方法之一是减少窗体初始化期间生成的方法调用的数目。例如,Forms Designer(窗体设计器)生成的用于设置控件的    位置和大小的代码使用两个方法调用来设置这些属性,如下所示:
    this.textBox1.Location = new Point(10,20);
    this.textBox1.Size = new Size(72,23);
    使用 Bounds 属性可以将这两个方法调用统一成一个方法调用:
    this.textBox1.Bounds = new Rectangle(10,20,72,23);

  *自上而下地创建控件
  提高性能的另一种方法是在控件树中自上而下地初始化控件。例如,如果有一个包含许多控件的面板控件,请先创建面板,然后在面板上添  加控件。同样,设置控件的父属性而不是添加至控件集合,也可以提高性能。例如,请考虑在面板的控件集合中添加一个文本框:
  // 优化前
  // 创建一个新面板和文本框控件
  Panel panel1 = new Panel();
  TextBox textBox1 = new TextBox();
  // 设置 TextBox 控件的 Text 属性
  textBox1.Text = "我的文本";
  // 将 TextBox 添加至面板的控件集合中
  panel1.Controls.Add(this.textBox1);
  // 将面板添加至窗体的控件集合中
  this.Controls.Add(panel1);
  ... // 在此处添加后续控件
  使用自上而下和父级处理技术优化此代码片断将生成以下代码片断:
  // 优化后
  // 创建一个新面板和文本框控件
  Panel panel1 = new Panel();
  TextBox textBox1 = new TextBox();
  // 使当前窗体成为面板的父级
  this.panel1.Parent = this;
  // 使面板成为 TextBox 的父级
  this.textBox1.Parent(this.panel1);
  // 设置 TextBox 控件的 Text 属性
  textBox1.Text = "我的文本";
... // 在此处添加后续控件

四.数据库优化总结

   在数据库设计和编写程序时往往没有考虑到数据库的数据量增加时对程序的影响。一旦数据量增加程序运行会越来越慢。
   在对数据库进行增加,删除,修改,查询时应坚持一个原则,在保持功能不变的前提下,应尽量减少I/O操作和对数据库的访问次数。
   数据库的逻辑设计、包括表与表之间的关系是优化关系型数据库性能的核心。一个好的逻辑数据库设计可以为优化数据库和应用程序打下良好的基础。


提问:下面两种Sql命令的执行方式,那种速度会快,效率会高?原因是什么?或者两种都不好.
     公共命令:SqlConnection cn=new SqlConnection(strCn);  SqlCommand cmd=cn.CreateCommand();                  cn.Open();   string strCmd="";
     方式一:循环,每条命令都执行一次数据库插入操作。 
            for (int i=0;i<125;i++) 
              {  
                strCmd="Insert Into Table (index) Values (" + i.ToString() + ")";                   cmd.CommandText=strCmd;
                cmd.ExecuteNonQuery(); 
              }
    方式二:循环获得插入字符串,最后统一执行。 
            for (int i=0;i<125;i++)
              {  
                strCmd +="Insert Into Table (index) Values (" + i.ToString() + ");"; 
              }   
            cmd.CommandText=strCmd; 
            cmd.ExecuteNonQuery(); 

提问:下面的两对Sql命令中是A快,是B快?假定所有显示出来的列都是索引列!
     [A] Select * From Table Where Field1<>'value' 
     [B] Select * From Table Where Field1>'value' Or Field1<'value'

     [A] Select * From Table Where Field1 In (Select Field4 From Table2 Where Table2.Field4=Table.Field3)
     [B] Select * From Table Where Exists(Select Field4 From Table2 Where Table2.Field4=Table.Field3 And          Table.Field1=Table2.Field4)

 

 
解答:提问一的两种方式都不可取,采用存储过程为最优方法。但是AnClor优化没有考虑存储过程所以,暂时抛开存储过程
   正确的方法应是采用临时表操作.
     
     提问二(1)A比B要快因为前者的比较次数比后者的比较次数要少。
      (2)如果查询条件少的话用IN更快,如果条件多应用Exists 

posted @ 2005-07-11 16:53  永恒的风景  阅读(322)  评论(0编辑  收藏  举报