分页查询算法实践

 

马上要毕业了,心里很迷茫,感觉真的时间飞逝,软件真的博大精深,特别.NET平台在Microsoft下变化之迅猛,个人总是赶不上技术的日新月异。哎,希望自己能早日走上设计之路。

闲来无事便根据自己大学四年项目实践经验,想实现一些常用模块的抽象和集成。考虑了一下觉得先该从分页查询入手,便简单的设计了下,现目前版本实现了单表的基本分页查询。我知道博客园了已经有很多前辈做了这个,本人设计能力和前辈们比那就欠缺多了,有那里不足的望指出,大家共同进步。

下载代码:WolfPager下载

主要采用工厂模式创建实现了PageSqlBase的对象,然后可以利用对象的GetSql()方法返回查询Sql语句。我的目的是生成sql语句并非直接从数据库取得数据,因为我认为如果这样将会增加耦合度增加,不易于移植通用,也不与分页控件结合,于是为了降低耦合度,我认为分页控件的职责是UI的显示而并非分页算法等的处理,更非数据的读取。

1.VS类图为:

 

2其中PageSqlBase抽象类为:

 

 


代码

 1 namespace Wolf.Pager
 2 {
 3     public abstract class PageSqlBase
 4 {
 5 //查询信息
 6         public SearchInfo SearchInfo
 7         {
 8             get;
 9             set;
10         }
11 //Page信息
12         public PageInfo PageInfo
13         {
14             get;
15             set;
16         }
17         public abstract string GetSql();
18     }
19 }
20 

 

3 我在类库实现了多种分页算法,网上到处都有算法的描述,在这里我就不讲解了。只展示一下针对SqlServer低版本(2000)的分页算法选择类,因他的算法用Top并且不同的算法针对不同的主键和排序形式,为了效率的优化故应该选择不同的算法。它采用的适配器的方式实现的。

 

 


代码

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 
 6 namespace Wolf.Pager
 7 {
 8     public class SQLServerLowerLevelPageSql:PageSqlBase
 9     {
10         public override string GetSql()
11         {
12             if (PageInfo == null || SearchInfo == null)
13             {
14                 throw new ArgumentNullException("Page信息和Search信息不能为空!");
15             }
16             return PageSqlChoise().GetSql();
17         }
18 
19         protected virtual PageSqlBase PageSqlChoise()
20         {
21             if (SearchInfo.UniqueFieldCollection != null)
22             {
23                 if (SearchInfo.UniqueFieldCollection.Count == 1)
24                 {
25                     if (SearchInfo.OrderExpress != null)
26                     {
27                         if (SearchInfo.OrderExpress.Count == 1 && SearchInfo.OrderExpress[0].Filed.ToLower()
28                             .Equals(SearchInfo.UniqueFieldCollection[0].Name.ToLower()))
29                         {//单键唯一排序字段
30                             return InitPageSql(new TOPMAXPageSql());
31                         }
32                         else// 单键多排序
33                         {
34                             return InitPageSql(new TOPMutilpOrderPageSql());
35                         }
36                     }
37                     else//单键无排序(默认键值排序)
38                     {
39                         return InitPageSql(new TOPMAXPageSql());
40                     }
41                 }
42                 else//联合(多)键
43                 {
44                     return InitPageSql(new TopMutilpKeyPageSql());
45                 }
46             }
47             else if (SearchInfo.OrderExpress != null && SearchInfo.OrderExpress.Count > 0)
48                 //无键(联合建作为排序字段)//设计时把联合建作为了排序字段
49             {
50                 return InitPageSql(new TopMutilpKeyPageSql());
51             }
52             else
53             {
54                 throw new ArgumentNullException("Page信息和Search信息不能为空!");
55             }
56 
57         }
58 
59         private PageSqlBase InitPageSql(PageSqlBase psb)
60         {
61             psb.SearchInfo = SearchInfo;
62             psb.PageInfo = PageInfo;
63             return psb;
64         }
65     }
66 }
67 
68 
69 

 

4: 工厂类的实现方式代码如下:

 

 


代码

  1 using System;
  2 using System.Collections;
  3 using System.Reflection;
  4 
  5 namespace Wolf.Pager
  6 {
  7     public class PageFactory
  8     {        
  9         private static readonly PageFactory pageFactory = new PageFactory();
 10         private Hashtable ht;
 11         private PageFactory()
 12         {
 13             ht = new Hashtable();
 14         }
 15         public static PageFactory Instance
 16         {
 17             get
 18             {
 19                 return pageFactory;
 20             }
 21         }
 22 
 23         /// <summary>
 24         /// 根据配置节创建分页算法:数据库类型的配置优秀权大于算法Dll的配置;
 25         /// </summary>
 26         /// <returns></returns>
 27         public PageSqlBase Create()
 28         {
 29             try
 30             {
 31                 try
 32                 {
 33 //先检查Config中是否配置了数据库类型,优先级高些
 34                     string DataBaseType = System.Configuration.ConfigurationManager.AppSettings["DataBaseType"].ToString();
 35                     DataBaseType dbtype = (DataBaseType)Enum.Parse(typeof(DataBaseType), DataBaseType, true) ;
 36                     return Create(dbtype);
 37                 }
 38                 catch (Exception)
 39                 {
 40                 }
 41 //检查Config中是否配置了算法程序信息
 42                 string dll = System.Configuration.ConfigurationManager.AppSettings["Assembly"].ToString();
 43                 string name = System.Configuration.ConfigurationManager.AppSettings["NameSpace"] == null ? System.Configuration.ConfigurationManager.AppSettings["Assembly"].ToString()
 44                     : dll;
 45                 string type = System.Configuration.ConfigurationManager.AppSettings["Type"].ToString();
 46                 if (string.IsNullOrEmpty(dll) || string.IsNullOrEmpty(type))
 47                 {
 48                     throw new InvalidOperationException("没有配置PageSql节");
 49                 }
 50                 return Create(dll, name, type);
 51             }
 52             catch (NullReferenceException)
 53             {
 54 
 55                 throw new InvalidOperationException("不存在相应配置PageSql节");
 56             }
 57 
 58 
 59         }
 60 
 61         public PageSqlBase Create(string dll, string type)
 62         {
 63             return Create(dll, dll, type);
 64         }
 65 
 66         public PageSqlBase Create(string dll, string name, string type)
 67         {
 68 //缓存,减少程序集的加载
 69             string key = (dll + "$" + name + "." + type).ToLower();
 70             if (ht.ContainsKey(key) && ht[key] != null)
 71             {
 72                 Type ty = ht[key].GetType();
 73                 object obj = ty.Assembly.CreateInstance(ty.FullName, true);
 74                 return obj as PageSqlBase;
 75             }
 76             Assembly asm = Assembly.Load(dll);
 77             Type t = asm.GetType(name + "." + type, true, true);
 78             if (t.IsAbstract || t.IsInterface || !typeof(PageSqlBase).IsAssignableFrom(t))
 79             {
 80                 throw new ArgumentException("当前参数不合法");
 81             }
 82             PageSqlBase pageSql = asm.CreateInstance(name + "." + type) as PageSqlBase;
 83             ht.Add(key, pageSql);
 84             return pageSql;
 85         }
 86 
 87         public PageSqlBase Create(DataBaseType dataBase)
 88         {
 89             switch (dataBase)
 90             {
 91                 case DataBaseType.DB2:
 92                     return DB2Arithmetic();
 93                 case DataBaseType.MySQL:
 94                     return MySqlArithmetic();
 95                 case DataBaseType.Oracel:
 96                     return OracelArithmetic();
 97                 case DataBaseType.SQLServerHightLevel:
 98                     return SQLServerHightLevelArithmetic();
 99                 case DataBaseType.SQLServerLowerLevel:
100                     return SQLServerLowerLevelArithmetic();
101                 default:
102                     return DefaultArithmetic();
103             }
104         }
105 
106         protected virtual PageSqlBase DB2Arithmetic()
107         {
108             return new DB2PageSql();
109         }
110 
111         protected virtual PageSqlBase MySqlArithmetic()
112         {
113             return new MySqlLimitPageSql();
114         }
115 
116         protected virtual PageSqlBase OracelArithmetic()
117         {
118             return new OraclePageSql();
119         }
120 
121         protected virtual PageSqlBase SQLServerHightLevelArithmetic()
122         {
123             return new MSSQL2005Row_NumberPageSql();
124         }
125 
126         protected virtual PageSqlBase SQLServerLowerLevelArithmetic()
127         {
128             return new SQLServerLowerLevelPageSql();
129         }
130 
131         protected virtual PageSqlBase DefaultArithmetic()
132         {
133             return new TOPMutilpOrderPageSql();
134         }
135     }
136 }
137 
138 

 

 

我的测试配置Configu为:

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

 <appSettings>

    <add key="DataBaseType" value="SQLServerLowerLevel"/>

    <!--<add key="Assembly" value="ConsoleTest"/>

    <add key="NameSpace" value="ConsoleTest"/>

    <add key="Type" value="Program"/>-->

 </appSettings>

</configuration>

测试结果性能比较高效,具体大家把代码下载看。

 本版本只是一个初步的实践摸索版本,离使用还应该差一些,我会有时间在改进,主要应该还要加入:

1:多表查询的分页方式。

2:GroupBy分组统计方式的分页查询。

3:添加是内存数据统计的类库。

4:缓存机制的加入(初步打算用OS的页面置换算法LRU(最近最少使用),加入超时减少缓存带来的数据不一致性)。

  分页控件的设计暂时没考虑太多,我认为Web控件应该可以支持URl、PoatBack、Ajax三种方式,具体实现可以用简单工厂。Winform的当然就一种方式了。数据库处理应该有程序员了事件代码中挂载。UI和BL层必须与数据层相隔离。

 

希望能先多开发些常用模块,减少以后的代码量,加快开发速度。我的目标是能开发一个小型管理系统的通用开发和配置平台。

作者:破  狼 
出处:http://www.cnblogs.com/whitewolf/ 
本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。该文章也同时发布在我的独立博客中-个人独立博客博客园--破狼51CTO--破狼。http://www.cnblogs.com/whitewolf/archive/2010/03/12/WolfPager.html

时间: 2024-09-07 09:54:38

分页查询算法实践的相关文章

深入实践Spring Boot3.1.3 分页查询设计

3.1.3 分页查询设计 对于新型的Neo4j数据库来说,由于它的资源库遵循了JPA的规范标准来设计,在分页查询方面有的地方还不是很完善,所以在分页查询中,设计了一个服务类来处理,如代码清单3-3所示.其中,使用Class<T>传入调用的实体对象,使用Pageable传入页数设定和排序字段设定的参数,使用Filters传入查询的一些节点属性设定的参数. 代码清单3-3 Neo4j分页查询服务类 @Service public class PagesService<T> {    

深入实践Spring Boot3.2.5 分页查询控制器

3.2.5 分页查询控制器 列表数据的查询使用分页的方法,按提供的查询字段参数.页码.页大小及其排序字段等参数,通过调用数据管理模块进行查询,然后返回一个分页对象Page,如代码清单3-8所示.这里的分页查询调用了3.1.3节定义的分页查询服务类. 代码清单3-8 电影分页查询控制器     @RequestMapping(value="/list") public Page<Movie> list(HttpServletRequest request) throws Ex

数据库分页查询方法

在这里主要讲解一下MySQL.SQLServer2000(及SQLServer2005)和ORCALE三种数据库实现分页查询的方法. 可能会有人说这些网上都有,但我的主要目的是把这些知识通过我实际的应用总结归纳一下,以方便大家查询使用. 下面就分别给大家介绍.讲解一下三种数据库实现分页查询的方法. 一. MySQL 数据库分页查询 MySQL数据库实现分页比较简单,提供了LIMIT函数.一般只需要直接写到sql语句后面就行了. LIMIT子句可以用来限制由SELECT语句返回过来的数据数量,它有

Oracle分页查询排序数据重复问题

  在项目开发过程中大量的使用了分页查询,当想要让数据按照日期排序时,出现了很多重复的数据出现. 造成这一问题出现的原因是:在数据中,日期的值不是唯一的.我们知道 Oracle的分页查询是没有进行任何排序操作的,Oracle是顺序的从数据块中读取符合条件的数据返回到客户端.而Oracle的排序算法不具有稳定性,也就是说,对于键值相等的 数据,这种算法完成排序后,不保证这些键值相等的数据保持排序前的顺序. 解决这一问题的方法就是在后边增加一个唯一性列,比如主键,问题解决. select * fro

表格存储新手指南:如何实现分页查询

本篇文章会介绍如何在表格存储上实现分页查询. 有别于传统关系型数据库支持的翻页查询,在NoSQL的数据模型和API上,实现分页功能会有以下的限制,需要特别注意: 不支持获取整个范围的行数,即无法计算总的页数. 不建议使用设置offset来跳页,因为offset的过滤是在客户端做,服务端不管如何,都会扫描读出那么多的数据.若offset设定过大,则可能导致本次查询时间过长. 最佳实践是只提供顺序翻页的功能,一页一页顺序往下翻. 下面是一个实现分页读接口的示例代码,提供offset过滤以及读取指定页

数据库分页查询方法_数据库其它

可能会有人说这些网上都有,但我的主要目的是把这些知识通过我实际的应用总结归纳一下,以方便大家查询使用. 下面就分别给大家介绍.讲解一下三种数据库实现分页查询的方法. 一. MySQL 数据库分页查询 MySQL数据库实现分页比较简单,提供了LIMIT函数.一般只需要直接写到sql语句后面就行了. LIMIT子句可以用来限制由SELECT语句返回过来的数据数量,它有一个或两个参数,如果给出两个参数, 第一个参数指定返回的第一行在所有数据中的位置,从0开始(注意不是1),第二个参数指定最多返回行数.

JDBC使用游标实现分页查询的方法_java

本文实例讲述了JDBC使用游标实现分页查询的方法.分享给大家供大家参考,具体如下: /** * 一次只从数据库中查询最大maxCount条记录 * @param sql 传入的sql语句 * @param startNo 从哪一条记录开始 * @param maxCount 总共取多少条记录 */ public void getData(String sql,int startNo,int maxCount){ Connection conn = ConnectionUtil.getConnec

详解SQLServer和Oracle的分页查询_MsSql

不管是DRP中的分页查询代码的实现还是面试题中看到的关于分页查询的考察,都给我一个提示:分页查询是重要的.当数据量大的时候是必须考虑的.之前一直没有花时间停下来好好总结这里.现在又将Oracle视频中关于分页查询的内容看了一遍,发现很容易就懂了. 1.分页算法     最开始我在网上查找资料的时候,看到很多分页内容,感觉很多很乱.其实不是这样.网上那些资料大同小异.问题出在了我自己这里.我没搞明白进行分页的前提是什么?我们都知道只要有分页都会涉及这些变量:每页又多少条记录(pageSize).当

分页查询的排序问题

前两天刚刚看完Tom的EFFECTIVE ORACLE BY DESIGN的第八章,从里面学到不是东西.同时也发现一个问题:Tom给出的关于分页以及ROWNUM的时候,几乎包含了我前几篇关于分页文章中的所有关键点. 于是,打算补充一篇关于分页排序问题的文章,这篇文章中的内容是Tom书中没有的. SQL> CREATE TABLE TEST AS SELECT ROWNUM ID, A.* FROM DBA_OBJECTS A; 表已创建. SQL> EXEC DBMS_STATS.GATHER