现在的位置: 首页 > 综合 > 正文

分页代码及相应SQL效率的分析(附:测试报告结果)

2012年01月23日 ⁄ 综合 ⁄ 共 5995字 ⁄ 字号 评论关闭

前阵子一直在研究一个老问题,就是分页效率问题。虽然网上代码不计其数,但是大部分都是雷同的,不尽如人意。在此我把这几天的研究成果给大家分享下,希望对各位程序开发人员有所帮助。(注:这里没有研究分页缓存机制的问题,只是从优化SQL语句考虑)。

 

在数据访问层中:

代码:

private const string GET_SINGLE_PAGE_MESSAGE_LIST_FOR_SQL_TOP_IN = "SELECT TOP {0} * FROM (SELECT TOP {1} Id,Title,AddUser,CreateTime FROM [Messages] WHERE Id NOT IN (SELECT TOP {2} Id FROM [Messages])) as [Msg]";

        /// <summary>

        /// Get Single Page Message List,SQLTOP,Not In方式

        /// </summary>

        /// <param name="pgpo">PaginationGoPageObject</param>

        /// <returns>IList</returns>

        public static IList GetSinglePageMessageListForSqlTopIn(PaginationGoPageObject pgpo)

        {

            DataBaseInstance dbInstance = new DataBaseInstance();

            dbInstance.Open(1);

            //不能通过参数的方式来实现

            string GET_SINGLE_PAGE_MESSAGE_LIST_FOR_SQL_TOP_IN_str = string.Format(GET_SINGLE_PAGE_MESSAGE_LIST_FOR_SQL_TOP_IN, pgpo.PageSize, pgpo.PageSize * pgpo.CurrentPage, pgpo.PageSize * (pgpo.CurrentPage - 1));

 

            dbInstance.SqlCommandText = GET_SINGLE_PAGE_MESSAGE_LIST_FOR_SQL_TOP_IN_str;

            IList MsgList = dbInstance.ExecuteList();

            dbInstance.Close();

 

            IList messageDataObjects;

            if (MsgList == null || MsgList.Count == 0)

            {

                messageDataObjects = null;

            }

            else

            {

                messageDataObjects = new ArrayList(MsgList.Count);

                foreach (IDictionary dicMessageDO in MsgList)

                {

                    MessageDataObject messageDO = new MessageDataObject();

                    messageDO.Id = Convert.ToInt32(dicMessageDO["ID"]);

                    messageDO.Title = dicMessageDO["TITLE"].ToString();

                    messageDO.AddUser = dicMessageDO["ADDUSER"].ToString();

                    messageDO.CreateTime = (DateTime)dicMessageDO["CREATETIME"];

                    //messageDO.SortId = (int)dicMessageDO["SORTID"];

                    //messageDO.Message = dicMessageDO["MESSAGE"].ToString();

                    //messageDO.Reply = dicMessageDO["REPLY"].ToString();

                    //messageDO.Image = dicMessageDO["IMAGE"] as byte[];

 

                    messageDataObjects.Add(messageDO);

                }

            }

            return messageDataObjects;

        }

 

 

private const string GET_SINGLE_PAGE_MESSAGE_LIST_FOR_SQL_TOP_MAX = "SELECT TOP {0} Id,Title,AddUser,CreateTime FROM [Messages] WHERE (Id > (SELECT MAX(Id) FROM (SELECT TOP {1} Id FROM [Messages] ORDER BY Id) AS [Msg_temp]))";

        /// <summary>

        /// Get Single Page Message List,SQLTOP,MAX方式

        /// </summary>

        /// <param name="pgpo">PaginationGoPageObject</param>

        /// <returns>IList</returns>

        public static IList GetSinglePageMessageListForSqlTopMax(PaginationGoPageObject pgpo)

        {

            DataBaseInstance dbInstance = new DataBaseInstance();

            dbInstance.Open(1);

            //不能通过参数的方式来实现

            string GET_SINGLE_PAGE_MESSAGE_LIST_FOR_SQL_TOP_MAX_str = null;

 

            if (pgpo.CurrentPage == 1)//判断是否为首页

            {

                GET_SINGLE_PAGE_MESSAGE_LIST_FOR_SQL_TOP_MAX_str = string.Format("SELECT TOP {0} Id,Title,AddUser,CreateTime FROM [Messages]", pgpo.PageSize);

            }

            else

            {

                GET_SINGLE_PAGE_MESSAGE_LIST_FOR_SQL_TOP_MAX_str = string.Format(GET_SINGLE_PAGE_MESSAGE_LIST_FOR_SQL_TOP_MAX, pgpo.PageSize, pgpo.PageSize * (pgpo.CurrentPage - 1));

            }

           

            dbInstance.SqlCommandText = GET_SINGLE_PAGE_MESSAGE_LIST_FOR_SQL_TOP_MAX_str;

            IList MsgList = dbInstance.ExecuteList();

            dbInstance.Close();

 

            IList messageDataObjects;

            if (MsgList == null || MsgList.Count == 0)

            {

                messageDataObjects = null;

            }

            else

            {

                messageDataObjects = new ArrayList(MsgList.Count);

                foreach (IDictionary dicMessageDO in MsgList)

                {

                    MessageDataObject messageDO = new MessageDataObject();

                    messageDO.Id = Convert.ToInt32(dicMessageDO["ID"]);

                    messageDO.Title = dicMessageDO["TITLE"].ToString();

                    messageDO.AddUser = dicMessageDO["ADDUSER"].ToString();

                    messageDO.CreateTime = (DateTime)dicMessageDO["CREATETIME"];

                    messageDataObjects.Add(messageDO);

                }

            }

            return messageDataObjects;

        }

 

 

private const string GET_SINGLE_PAGE_MESSAGE_LIST_FOR_SQL_CURSOR = "SELECT TOP {0} Id,Title,AddUser,CreateTime FROM [Messages]";

        /// <summary>

        /// Get Message List For Single,游标方式

        /// </summary>

        /// <param name="pgpo">PaginationGoPageObject</param>

        /// <returns>IList</returns>

        public static IList GetSinglePageMessageListForSqlCursor(PaginationGoPageObject pgpo)

        {

            DataBaseInstance dbInstance = new DataBaseInstance();

            dbInstance.Open(1);

            //不能通过参数的方式来实现

            string GET_SINGLE_PAGE_MESSAGE_LIST_FOR_SQL_CURSOR_str = string.Format(GET_SINGLE_PAGE_MESSAGE_LIST_FOR_SQL_CURSOR, pgpo.PageSize * pgpo.CurrentPage);

 

            dbInstance.SqlCommandText = GET_SINGLE_PAGE_MESSAGE_LIST_FOR_SQL_CURSOR_str;

            IList MsgList = dbInstance.ExecuteListForPage(pgpo.PageSize,pgpo.CurrentPage);

            dbInstance.Close();

 

            IList messageDataObjects;

            if (MsgList == null || MsgList.Count == 0)

            {

                messageDataObjects = null;

            }

            else

            {

                messageDataObjects = new ArrayList(MsgList.Count);

                foreach (IDictionary dicMessageDO in MsgList)

                {

                    MessageDataObject messageDO = new MessageDataObject();

                    messageDO.Id = Convert.ToInt32(dicMessageDO["ID"]);

                    messageDO.Title = dicMessageDO["TITLE"].ToString();

                    messageDO.AddUser = dicMessageDO["ADDUSER"].ToString();

                    messageDO.CreateTime = (DateTime)dicMessageDO["CREATETIME"];

                    messageDataObjects.Add(messageDO);

                }

            }

            return messageDataObjects;

        }

 

 

以上用了SQL3种方式:Not In方式,Max()方式,游标方式。

在我的电脑上DELL品牌机(型号:E520,内存增至2G,双核CPU),我导入了1000万条数据,每页显示10条记录。

以下是测试报告。

 

前面的分页显示时间

最后的分页显示时间

Not In方式

1秒内

6秒左右

Max()方式

1秒内

4-5

游标方式

1秒内

8秒左右

抱歉!评论已关闭.