如果定义了主键的话,用DataTable.Rows.Find 应该能提高速度private void FindInPrimaryKeyColumn(DataTable table, long pkValue) { // Find the number pkValue in the primary key // column of the table. DataRow foundRow = table.Rows.Find(pkValue); // Print the value of column 1 of the found row. if(foundRow != null) Console.WriteLine(foundRow[1]); }
像这种情况,我们都是用排序的办法,把需要的数据排序到最前面或者尽量靠近最前面,这样速度相对能提高不少。。你可以试试。。
long pkValue)
{
// Find the number pkValue in the primary key
// column of the table.
DataRow foundRow = table.Rows.Find(pkValue); // Print the value of column 1 of the found row.
if(foundRow != null)
Console.WriteLine(foundRow[1]);
}
虽然你是需要用Select()找到你符合条件的那条数据,但是你的DataTable数据显示在窗口上能显示10万条?我想即使绑定到dataGridView上面也就显示几十条吧。所以解决方法就是一旦你在Select()的过程中显示了能够填充那几十条记录的时候你就立刻显示,剩下的在你显示之后处理也不迟
别理他 哈哈!
话说我基本不用DATATABLE这种东西,通常都是LINQ100多毫秒的话我就不会关心效率问题了!没研究过100秒我才关心!
首先,楼主是说SELECT()的效率问题,跟绑定无关这是查询。。其次,执行SELECT之后你BREAK掉它的线程我看看你怎么实现的!
恩无图无真相。你弄个BREAK的代码我看看先!上图上图!!!
不要使用 select,
RowFilter 更是扯蛋, 尤其数据已经绑定到界面的情况下,
各位看官可以尝试一下那个效率有多低.
这都神马跟神马,楼主根本没假定多少条记录的查询结果,如果是10W的用户信息被CACHE起来呢?需要精确定位到用户信息时的效率问题,你什么多行又记录的,人家就是问,DATATABLE的SELECT()方法的效率问题,能不能用别的查询方法替代,或者说先对DATATABLE建索引这样的方式可以提高查询效率你都什么跟什么呀!你看楼主理你么
额想到这里,突然想到SQL分区的概念,楼主能否按照DATATABLE的某些排序方式、索引或者行号什么的拆分,然后用多线程去查?
+1数据量大的时候当然还是充分利用主键了if (dt.PrimaryKey == null || dt.PrimaryKey.Length == 0)
{
dt.PrimaryKey = new DataColumn[] { dt.Columns["PK_ColunmeName"] };
}
个人感觉,还是应该保存到DB里,并不是所有记录一直都在用不是?
一个线程插入DB,一个线程查
插入不过几条数据,数据库再加入索引,就算每秒查也不会慢。
通常100W级别的数据,带索引检索不过是ms级别的响应。
内存是有限的,如果是一直运行7x24H,再大内存也不够。可能你觉得每次查询慢,是因为没有DB连接池,每次new connection都特别慢,
还是查询的代码哪块没整好。
如果主键有重复,就做个List。 不知可行不
10w 笔的数据,查询、检索如果在db端优化处理的好的话,应该比前端程式要好些的。
o my lady gaga尽量在SQL中完成把!!!!
难道客户要输出10万条记录的报表,你还不给打了?
如果1000个客户同时都需要输出巨量数据呢?
(比如财务/税务等系统,每个会计区间都需要输出实体单据,那种输出量是非常巨大,并且是高并发的)无论DBMS还是我们自己开发数据访问服务器(DAS),
(很多人乐此不疲的搞什么ORM,却不晓得设计一个真正OO的数据访问服务器)
都要充分利用内存来提高查询效率和访问速度,那种只依靠DBMS或者APP访问数据的做法都是不可取(低效率)的
简单描述策略就是:
数据库完成复杂查询,分批把数据送达APP-DAL或者DAS,然后再由DA分批送到客户端
在一个查询周期中,如果客户第二次调阅某页数据,就不会再劳驾DBMS和占用LINK了,
而客户端的开发大大简化,那看上去就是一遍遍不厌其烦的、单调的访问DAS
好像你理解错了,lz的意思是把所有数据都放到内存,怎么来优化查询(lz连第一都不想从数据库中获取)。
而不是搞什么第一次数据查询,然后缓存(当然这种模式可以考虑)。
另外,我一般用datatable 只是缓存一下用户的信息,在登录时,不用经常去读数据库。
如果楼主要查找某一个字段,或者说列,将这列的数据单独导出到一个SortList中,然后查找,或者你自己搞二分查找,这样效率能够很高。
数据库索引去硬盘或者数据库的缓存查找。程序也可以试试写算法给DataTable建索引啊。
按大小比较的就排序,按键值查询的就把相同键值的DataRow集合放到一个字典里去
比如Dictionary<String Key,List<DataRow>>之类的。
多个查找条件就弄几个字典。反正只是对DataRow的引用
还可以查查数据库索引的算法。
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
DataTable dt = GetTable();
Console.WriteLine("当前表总数量量=" + dt.Rows.Count);
IList<Demo> lists = GetLists(); string sql = "sName like '%999%' and sCity like '%第9%'"; while (true)
{
Console.WriteLine("自行循环查询耗时=" + searchByForeach(lists) + "毫秒");
Console.WriteLine("");
Console.WriteLine("以Linq查询耗时=" + searchByLinq(lists) + "毫秒");
Console.WriteLine("");
Console.WriteLine("按select查询耗时=" + searchBySelect(dt, sql) + "毫秒");
Console.WriteLine("");
Console.WriteLine("按Filter查询耗时=" + searchByFilter(dt, sql) + "毫秒");
Console.WriteLine(""); string s = Console.ReadLine();
if (s == "exit")
{
return;
}
}
} private static int searchBySelect(DataTable dt,string sql)
{
DateTime start = DateTime.Now;
DataRow[] drs = dt.Select(sql);
Console.WriteLine("求取的数据数量=" + drs.Length);
//Console.WriteLine(start.ToString("mm:ss fff") + DateTime.Now.ToString("mm:ss fff"));
TimeSpan ts = DateTime.Now - start; return ts.Milliseconds;
} private static int searchByFilter(DataTable dt, string sql)
{
DateTime start = DateTime.Now;
dt.DefaultView.RowFilter = sql;
int count = dt.DefaultView.Count;
Console.WriteLine("求取的数据数量=" + count);
TimeSpan ts = DateTime.Now - start; return ts.Milliseconds;
} private static int searchByLinq(IList<Demo> lists)
{
DateTime start = DateTime.Now;
var values = from obj in lists
where obj.Name.Contains("999")
&& obj.City.Contains("第9")
select obj;
int count = values.Count(); Console.WriteLine("求取的数据数量=" + count);
TimeSpan ts = DateTime.Now - start; return ts.Milliseconds;
} private static int searchByForeach(IList<Demo> lists)
{
DateTime start = DateTime.Now; int count = 0;
foreach (Demo info in lists)
{
if (info.Name.Contains("999") && info.City.Contains("第9"))
{
count++;
}
} Console.WriteLine("求取的数据数量=" + count);
TimeSpan ts = DateTime.Now - start; return ts.Milliseconds;
}
private static DataTable GetTable()
{
DataTable dt = new DataTable();
dt.Columns.Add("sName", typeof(string));
dt.Columns.Add("sCity", typeof(string));
dt.Columns.Add("sId");
for (int i = 0; i < 100000; i++)
{
DataRow dr = dt.NewRow();
dr["sId"] = i.ToString();
dr["sName"] = "标准数据_" + i;
dr["sCity"] = "居住在第" + i + "城市"; dt.Rows.Add(dr);
} return dt;
} private static IList<Demo> GetLists()
{
IList<Demo> lists = new List<Demo>();
for (int i = 0; i < 100000; i++)
{
Demo info = new Demo();
info.Id = i.ToString();
info.Name = "标准数据_" + i;
info.City = "居住在第" + i + "城市"; lists.Add(info);
} return lists;
} public class Demo
{
public string Id = string.Empty;
public string Name = string.Empty;
public string City = string.Empty;
}
}
}
事实上,数据存储在内存中,按照现在的服务器的运算速度来看,对之查询速度非常之快,十几万条太小菜了.
唯一有问题的是,内存的消耗.只不过如果有这种业务需求的时候,再相对现在内存的价格以及操作系统64位的支持,这么一小点小小的内存支出完全不成问题.而且,在内存中存储十几万条数据似乎也不是很消耗内存的事情(取决于存储什么东西,按楼主的情况来看,恐怕是存储一些数字而已,占用的内存估计不多)
DataTable
查询只需10毫秒
条件是 往DataTable填充数据之后 要执行一次select(第一次速度 有点慢)
以后 查询速度会很快
行业:环保监测
情景回放:
存在大量的客户端(约300-400个),都使用tcp连接连接到服务器,然后客户端平均约23秒左右就发送一条文本数(该数据包含大约30-60条不等的真是数据)据到服务器(就是平均1/20秒服务器就收到一个数据),服务器收到数据对数据的合格性进行校验,更新内存中的数据显示异常数据的信息及对应客户端的信息,并写入到数据库中。
其中因为需要检验数据的合格性,就等于约在300*40*20【客户*客户端的监测设备数量*监测因子】寻找对应的数据,然后调用内存中的数据对传入数据进行校验,判断出异常后还有进行异常显示,最后还要联同校验结果写入数据库
在如此大量的数据写入动作中,如果每次收到数据然后都去读数据库,显然是不现实的,所以都是在程序运行的初期就把设定的校验值数据读到内存中去,然后数据库只进行数据写入动作。
处理方法:
当时我的处理过程是这样的
1、对于tcp连接选择多线程处理(当然的事情),但我的选择方式有点不同,我选择的是一个线程负责几个tcp连接。
2、对校验数据进行多次读取,并加入复合主键(根据传入的数据)
就是20w行数据按照客户端的编号规则分成若干个(我选择的50个),然后在建立一个客户索引表(只有几个字段:客户端编号,内存校验数据datatable名称,真实存放表名称),然后把这些表都添加到dataset中
3、在把这个dataset复制到线程中,就是每个线程都有一个这个dataset的副本供线程本身使用
4、当有数据传入时,先查找客户端编号,然后再在对应的datatable中查找校验值数据,这样对于异常客户端(没有客户端编号,或客户端编号异常)的数据能达到最快校验的效果
http://www.cnblogs.com/AloneSword/articles/801989.html