前段时间本人就<模糊查询>的增量查询做了一些简单的说明,但是我们也会遇到没有必要用这种方式的查询操作, 或者查询也只是临时的.必有必要在数据库中储存一些不需要经常访问的"关键字索引"记录,那么对这种数据查询
我们如何进行类似这种的有效的查询.今天就这个问题进行讨论.
在实际应用中我们经常对一些较大的数据进行模糊查询.本人就遇到要对近500万以上的一个用户表进行操作,比如
我们经常需要查询某个公司名,Email,或者就是用户名.进行查询用户详细信息的操作,对这部分的查询操作.也
许我们的客服忘记了公司全名,只是记住部分公司名,这样的查询就不可避免要用上模糊查询了.对这样大小的表即便我
们对表进行了有效优化,索引,但是进行查询的时候还是不时的遇到超时.当然我们照样也可以把操作时间限制的很长,
但是这样的时间等待多半客服会以为程序当机了...如何解决这部分的查询呢?
那么如何解决这个问题?
这就使我想起了增量搜索.但是原先的那个搜索实在是太复杂,那么我对其进行了小小的手术.
以下是大致的思路
1.查询时,每次只是提取大于上次搜索过的最后记录Id到本次查询最大记录范围内的信息的记录进行模糊查询,
这样获得记录的ID,存放于临时表中.
3.我们对以上的操作循环,当然不是无限制的循环,当操作超过我们所设定的超时时间后返回记录的ID,最后搜索的ID,以及
搜索未完成.如果已经搜索到最后ID时,返回所有搜索到的Id,最后ID,以及完成搜索.
当我们搜索完成后,并得到所有信息的ID后在根据这些ID获得信息内容.
这样查询的好处是,我们每次仅仅对一部分的数据进行模糊查询,避免超时无法获得结果错误.
如果这样的查询操作与 Ajax 结合,那将是一个完美的搜索...我们用Ajax在页面异步搜索,并将返回ID记录,如果搜索完成,显示
数据,但是如果没有完成,我们可以提示用户进行是否继续搜索,或者直接进行搜索直到完毕或者用户取消,这样我们不但完成
了我们所需要的搜索,而且这样的查询也非常有效,也就相应的减轻了服务器压力.
而我在这样实际应用中,在同样的数据量,同样的超时时间设定就能搜索出来信息.而普通的搜索是根本做不到的事情.往往他
们的结果只有超时.
下面我把写存储过程给大家.大家可以参考一下
最后需要注意的就是 @maxTime以及@maxTime参数的设置,@maxTime是循环时超时的时间,@maxSNum是指每次循环时最多数据的记录数 如果@maxTime设置过大,当处理过多数据时照样会发生超时,太小则每次搜索记录数不够,而@maxSNum设置过大造成第一次的 查询可能就已经超时,过小循环过多,影响操作效率.两者都会造成不同程度的资源浪费.所以一定要根据实际数据库来设置两个参数.
CREATE
PROCEDURE
[
p_getManyInfo
]
@keyWord
NVARCHAR
(
200
),
@maxTime int = 2000 ,
@maxSNum int = 1000 , @lastSid int = 1 OUTPUT,
@completed bit = 1 OUTPUT, @auto_id int
-- 参数说明 关键字,最大超时时间,每次循环提取记录数,最后搜索ID(返回),是否完成(返回),搜索起始ID
AS
BEGIN
SET @completed = 1 ;
SET @lastSid = @auto_id ;
DECLARE @maxId int ;
DECLARE @sql nvarchar ( 4000 );
DECLARE @t1 datetime , @t2 datetime ;
SET @sql = '' ;
-- 设置执行开始时间
SET @t1 = getdate ();
-- 获得当前表中最大ID
SELECT @maxId = MAX (id) FROM fabu;
-- 临时表1,用于储存返回ID
CREATE TABLE #TBL ( idtmp INT );
-- 开始循环
WHILE ( 2 > 1 )
BEGIN
-- 提取指定条数临时信息并且ID大于上次搜索的最后ID
PRINT @lastSid ;
SET @sql = ' INSERT INTO #TBL SELECT [id] FROM fabu
WHERE [id]> ' + CONVERT ( NVARCHAR ( 30 ), @lastSid ) + ' AND [id]< ' + CONVERT ( NVARCHAR ( 30 ),( @lastSid + @maxSNum ))
+ ' AND title like [email=] ' target = ' _blank ' > [ B ] + ' % '' ; ' ;
EXEC sp_executesql @sql ;
-- 对上一步提取的记录进行模糊查询或者相其他应的条件查询并添加到临时表中
SET @lastSid = @lastSid + @maxSNum ;
PRINT @lastSid ;
-- 设置以上操作完毕后的时间
SET @t2 = getdate ();
-- 一下就是对操作前,操作后的时间进行计算,获得实际操作时间,并判断时间是否超过了我们所设定的时间
IF convert ( int , datediff (ms, @t1 , @t2 )) > @maxTime
BEGIN
-- 如果超时,我们清空所有临时资源,返回未成功以及当前已搜索到的数据.
SELECT @completed = 0 ;
SELECT * FROM #TBL ORDER BY idtmp;
DROP TABLE #TBL;
BREAK
END
ELSE IF @lastSid >= @maxId
BEGIN
-- 如果已经搜索到最后Id(搜索完毕),返回相应数据
SELECT @completed = 1 ;
SELECT * FROM #TBL ORDER BY idtmp;
DROP TABLE #TBL;
BREAK
END
-- 不符合以上任何一种条件则不断循环知道符合以上条件之一
END
END
@maxTime int = 2000 ,
@maxSNum int = 1000 , @lastSid int = 1 OUTPUT,
@completed bit = 1 OUTPUT, @auto_id int
-- 参数说明 关键字,最大超时时间,每次循环提取记录数,最后搜索ID(返回),是否完成(返回),搜索起始ID
AS
BEGIN
SET @completed = 1 ;
SET @lastSid = @auto_id ;
DECLARE @maxId int ;
DECLARE @sql nvarchar ( 4000 );
DECLARE @t1 datetime , @t2 datetime ;
SET @sql = '' ;
-- 设置执行开始时间
SET @t1 = getdate ();
-- 获得当前表中最大ID
SELECT @maxId = MAX (id) FROM fabu;
-- 临时表1,用于储存返回ID
CREATE TABLE #TBL ( idtmp INT );
-- 开始循环
WHILE ( 2 > 1 )
BEGIN
-- 提取指定条数临时信息并且ID大于上次搜索的最后ID
PRINT @lastSid ;
SET @sql = ' INSERT INTO #TBL SELECT [id] FROM fabu
WHERE [id]> ' + CONVERT ( NVARCHAR ( 30 ), @lastSid ) + ' AND [id]< ' + CONVERT ( NVARCHAR ( 30 ),( @lastSid + @maxSNum ))
+ ' AND title like [email=] ' target = ' _blank ' > [ B ] + ' % '' ; ' ;
EXEC sp_executesql @sql ;
-- 对上一步提取的记录进行模糊查询或者相其他应的条件查询并添加到临时表中
SET @lastSid = @lastSid + @maxSNum ;
PRINT @lastSid ;
-- 设置以上操作完毕后的时间
SET @t2 = getdate ();
-- 一下就是对操作前,操作后的时间进行计算,获得实际操作时间,并判断时间是否超过了我们所设定的时间
IF convert ( int , datediff (ms, @t1 , @t2 )) > @maxTime
BEGIN
-- 如果超时,我们清空所有临时资源,返回未成功以及当前已搜索到的数据.
SELECT @completed = 0 ;
SELECT * FROM #TBL ORDER BY idtmp;
DROP TABLE #TBL;
BREAK
END
ELSE IF @lastSid >= @maxId
BEGIN
-- 如果已经搜索到最后Id(搜索完毕),返回相应数据
SELECT @completed = 1 ;
SELECT * FROM #TBL ORDER BY idtmp;
DROP TABLE #TBL;
BREAK
END
-- 不符合以上任何一种条件则不断循环知道符合以上条件之一
END
END