提建议者有分!!!!!

时间:2022-12-13 21:24:51
    我在开发一个三维图形软件,根据数据绘制三维图形。数据量很大,动辄上百兆。
在读取文件(一般是二进制的)数据时,读取数量均很大(有时是整个文件,有时
是其一部分)。有时一次连续读很多字节(如上千个),有时一次读取几个字节(如两
个,因为要有选择的读)。在前一种情况下,读取速度很快,后者就惨了!
    本来我想通过数据库管理这些数据,可用SQL Server7.0的结果表明,速度反而减
慢。并且我不能在发布软件时要用户购买一个SQL Server。
    每次读取数据时,需要根据数据所在位置读取,不一定有规律,可能根据用户的选择
确定。
    各位有什么建议?需要自己设计一个数据库?还是其他?


   BTW:对文件的Seek函数来说,Seek距离的大小有没有速度的不同?

38 个解决方案

#1


数据量不是很大,查找定位不是很复杂的时候,也没有复杂的查询和统计功能的时候,就建议不用数据库了。
你的数据文件的格式是不是可以优化一下。
还有可以一次读多点的数据到内存中,然后处理啊!
我看过一本Oracle的书,讲过一点数据读取优化的东西,好像可以参考一下。
但是忘了书名了。

#2


1 可以把所有数据放在1个文件里。
2 不要用数据库,速度只会更慢。

#3


3 可以用磁盘阵列,可以极大提高数据处理速度。

#4


用 File Mapping 來做應該十分適合.

#5


我有这样一个想法:

你的数据类型可能不都一样,比如说有圆,直线,曲线(比方说)那么它们存储的方式就会不同,如果把它们放在同一个文件中,检索时势必会引起速度上的下降;

现在如果建一个总的索引文件,另外根据数据的类型的不同各自建一个文件,比如index.3df,Line.3df.ircle.3df....
在索引文件中指明各个数据存储的简短信息,如类型号,ID号等.然后就可以在相应的文件中计算偏移量,直接读取相应的数据信息,这样的结构在读取几个字节时,效率会非常的高
读连续数据时,效率也不会输给原来的数据组织方式。

#6


用结构化存储把
iStorage,IStream

#7


To smartboyme(小东):
  实际上数据量还是很大的,有时几个G。
  如何一次读多点的数据?//bow
  

#8


To windindance(风之舞) 
   我的数据就是在一个文件中的。
To ahphone(阿丰) 
   实际上,我的数据只有一个类型:点。
   但很有规律,实际上我的数据是一个三维体中每个单位立方体的数据,这个三维体由多个面组
成,而每个面由多条线组成,最后一条线由多个点组成。如果将每个面的数据放到不同的文件中再
建立索引会不会提高速度?可对点有什么索引可建?

#9


用汇编试试。

#10


这里点的值就是单位立方体的值。

#11


up

#12


你可以用内存映射,将你的数据文件作为虚拟存储直接映射到内存中, 这样会块很多...

#13


我的意见是,没有复杂的查询和统计,就不要用数据库。
数据库的作用是用来对很多条相似性的数据组织的,便于查询和定位。

还有,如果使用SQL Server,用户的软件成本会提高很多,而且使用也不方便啊!

你的数据文件是单个大,还是数量多啊?

#14


图形数据文件不是极大,考虑运行的速度,应从处理数据的算法入手,数据库专门管理实际上使软件与数据之间存在了类似"中间商"的因素,不慢才怪!

#15



进行适当的缓冲

#16


你的点、线、面不可以用一个公式来表示吗?存储公式可比存储位置小多了。

#17


呵呵,你最好能在用到数据之前把数据全部装进来,或者有选择的装一部分
这样是最快的,避免频繁的访问磁盘,在这里需要有良好的磁盘存盘结构,最好能在内存中索引
然后用内存文件搞定!
OK!

#18


改改你的保存内容。不应只是点。
保存立方体可以只保存四个顶点...
我不清楚这些,只是建议。

#19


很明显是数据的结构设计的不好,而造成多次在硬盘上面搜索数据。
另外你可以使用带缓冲的文件读写来提高效率

#20




你可以自己设计一个读文件的缓冲区,每次读512字节的整数倍(如4K),分析完这个缓冲区的数据后再接着读.如果用SEEK, 同样要SEEK到512字节的边界再读,这样可大大提高效率。

这样程序会复杂一点,不过你会发现提高的效率会让你觉得非常值得...




#21



上面的算法适用于顺序处理文件(这样你可以只开设一个缓冲区,其中的数据处理完之后就可将其丢弃,如果考虑到数据结构的边界问题,你可能需要设置两个这个的缓冲区)。
如果要随机处理文件,最好还给每次读取的数据作一个缓冲,具体的算法可找一本操作系统原理的书,其中的文件处理过程可作为参考。

#22


更正:"两个这个" => "两个这样"

#23


声明:我的数据在同一个文件中,当然可以人工的分为多个文件。
    1、分为多个文件有没有必要?
    2、虽然可以开设缓冲区,但数据并不是处理一块就抛弃一块的,因为可能还要重新使用。
    3、数据结构基本上没有办法改变,用户的数据天生如此。只能是点的数值,而且不能用任何
公式表示,因为这是采集来的数据。
    4、通过改变磁盘结构(如磁盘阵列)加快速度,当前无法考虑,因为用户不希望对他们有
如此要求。
    大侠再出手!!!

#24


可以用免费的数据库啊,很多的:
比如mysql, postgresql等等。。。
它们都同时支持unix,windows

#25


你可以使用操作系统中内存管理的思想. 建立一个缓冲池,里面有若干缓冲区(根据需要建立),缓冲区中存有你最近读取的数据。 读数据时,如果缓冲区中已有,就可能直接从缓冲区中读取。如果没有,就从文件中读取,并将其加入至缓冲池中。如果缓冲池已满,根据一定的算法淘汰旧的缓冲区,如LRU算法等。

#26


你这种非结构化的数据通常使用数据库的效率反而不会高。

#27


shit~~~~~

这么过分的要求,哪你就一次把文件的所有数据读到内存里面去计算。
反正现在内存夜便宜

#28


哈哈,好办法。听说2G的内存条已研制出来了...

#29


为什么这么好的办法Kevin先想到?!!!!!!

#30


嘿嘿嘿

#31


自己设计一个数据库格式, 自己字节进行压缩....

#32


嘿嘿嘿 
   ————真黑!

#33


up

#34


up

#35


用文件映射
所谓文件映射不是把文件全读进来,而是由操作系统来帮你做缓冲,和换页算法。这东西很适合随机读大文件。优点如下:
1方便,不需复杂编程
2可以利用空闲的内存,内存不必非常大,但加一点就好一点。
3有顺序地址的访问,你可以在原有的文件外部建立索引,或什么东西来加速读取

此外,我想从数据本身的特性来入手是最有效的。

编码如下:
HANDLE m_File = ::(strPathname,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL)
HANDLE m_FileMap = ::CreateFileMapping(
(void*)0xFFFFFFFF,
NULL,
PAGE_READ,
0,1024,
NULL
);
ASSERT(m_FileMap != NULL);
if(GetLastError() == ERROR_ALREADY_EXISTS){
TRACE("the share memory has already existed!\n");
}
else{
TRACE("Create share memory\n");
}
void* m_pMapMem = (char*)::MapViewOfFile(this->m_FileMap,FILE_MAP_READ,0,0,0);
ASSERT(m_pMapMem != NULL);
//..............use it......................//
UnmapViewOfFile(m_pMapMem);
CloseHandle(m_File);
CloseHandle(m_FILEMap);

#36


参考一下硬盘的数据读取技术

#37


不好意思,小弟真是没办法了,老板下星期就
要我交任务,问题贴出来已经两个星期了,就是找不到答案,
所以真是sorry了,在这占用你们的空间,希望能给小弟一个答复!先谢谢了!!

我以CEditView为基类建了一个MDI(其他什么代码我也没写),
有如下要求:我打开一个*.asm文档,想在光标所在行设一个断点,
要达到如在bc设断点的效果,在VC怎么做?能详细点回答吗?
有例子给我就感激不尽了!!
或转到http://www.csdn.net/expert/topic/171/171611.shtm

本人邮箱:wrongt@163.com

#38


以前也做过类似的三维项目,我们是将数据分成基本图形类,然后再内存中以指针连表(用CList)管理。
保存时可在CDocument::Serialize()中直接对CList调用序列化函数。对文件时再恢复成指针连表CList使用。速度不慢。不过你必须为你的C3dPoint,CLine,CCircle等基本图形类添加Serialize()函数,而且必须由CObject派生,这样调用CList:Serialize时MFC会自动去调用这些基本图形类的Serialize().

#1


数据量不是很大,查找定位不是很复杂的时候,也没有复杂的查询和统计功能的时候,就建议不用数据库了。
你的数据文件的格式是不是可以优化一下。
还有可以一次读多点的数据到内存中,然后处理啊!
我看过一本Oracle的书,讲过一点数据读取优化的东西,好像可以参考一下。
但是忘了书名了。

#2


1 可以把所有数据放在1个文件里。
2 不要用数据库,速度只会更慢。

#3


3 可以用磁盘阵列,可以极大提高数据处理速度。

#4


用 File Mapping 來做應該十分適合.

#5


我有这样一个想法:

你的数据类型可能不都一样,比如说有圆,直线,曲线(比方说)那么它们存储的方式就会不同,如果把它们放在同一个文件中,检索时势必会引起速度上的下降;

现在如果建一个总的索引文件,另外根据数据的类型的不同各自建一个文件,比如index.3df,Line.3df.ircle.3df....
在索引文件中指明各个数据存储的简短信息,如类型号,ID号等.然后就可以在相应的文件中计算偏移量,直接读取相应的数据信息,这样的结构在读取几个字节时,效率会非常的高
读连续数据时,效率也不会输给原来的数据组织方式。

#6


用结构化存储把
iStorage,IStream

#7


To smartboyme(小东):
  实际上数据量还是很大的,有时几个G。
  如何一次读多点的数据?//bow
  

#8


To windindance(风之舞) 
   我的数据就是在一个文件中的。
To ahphone(阿丰) 
   实际上,我的数据只有一个类型:点。
   但很有规律,实际上我的数据是一个三维体中每个单位立方体的数据,这个三维体由多个面组
成,而每个面由多条线组成,最后一条线由多个点组成。如果将每个面的数据放到不同的文件中再
建立索引会不会提高速度?可对点有什么索引可建?

#9


用汇编试试。

#10


这里点的值就是单位立方体的值。

#11


up

#12


你可以用内存映射,将你的数据文件作为虚拟存储直接映射到内存中, 这样会块很多...

#13


我的意见是,没有复杂的查询和统计,就不要用数据库。
数据库的作用是用来对很多条相似性的数据组织的,便于查询和定位。

还有,如果使用SQL Server,用户的软件成本会提高很多,而且使用也不方便啊!

你的数据文件是单个大,还是数量多啊?

#14


图形数据文件不是极大,考虑运行的速度,应从处理数据的算法入手,数据库专门管理实际上使软件与数据之间存在了类似"中间商"的因素,不慢才怪!

#15



进行适当的缓冲

#16


你的点、线、面不可以用一个公式来表示吗?存储公式可比存储位置小多了。

#17


呵呵,你最好能在用到数据之前把数据全部装进来,或者有选择的装一部分
这样是最快的,避免频繁的访问磁盘,在这里需要有良好的磁盘存盘结构,最好能在内存中索引
然后用内存文件搞定!
OK!

#18


改改你的保存内容。不应只是点。
保存立方体可以只保存四个顶点...
我不清楚这些,只是建议。

#19


很明显是数据的结构设计的不好,而造成多次在硬盘上面搜索数据。
另外你可以使用带缓冲的文件读写来提高效率

#20




你可以自己设计一个读文件的缓冲区,每次读512字节的整数倍(如4K),分析完这个缓冲区的数据后再接着读.如果用SEEK, 同样要SEEK到512字节的边界再读,这样可大大提高效率。

这样程序会复杂一点,不过你会发现提高的效率会让你觉得非常值得...




#21



上面的算法适用于顺序处理文件(这样你可以只开设一个缓冲区,其中的数据处理完之后就可将其丢弃,如果考虑到数据结构的边界问题,你可能需要设置两个这个的缓冲区)。
如果要随机处理文件,最好还给每次读取的数据作一个缓冲,具体的算法可找一本操作系统原理的书,其中的文件处理过程可作为参考。

#22


更正:"两个这个" => "两个这样"

#23


声明:我的数据在同一个文件中,当然可以人工的分为多个文件。
    1、分为多个文件有没有必要?
    2、虽然可以开设缓冲区,但数据并不是处理一块就抛弃一块的,因为可能还要重新使用。
    3、数据结构基本上没有办法改变,用户的数据天生如此。只能是点的数值,而且不能用任何
公式表示,因为这是采集来的数据。
    4、通过改变磁盘结构(如磁盘阵列)加快速度,当前无法考虑,因为用户不希望对他们有
如此要求。
    大侠再出手!!!

#24


可以用免费的数据库啊,很多的:
比如mysql, postgresql等等。。。
它们都同时支持unix,windows

#25


你可以使用操作系统中内存管理的思想. 建立一个缓冲池,里面有若干缓冲区(根据需要建立),缓冲区中存有你最近读取的数据。 读数据时,如果缓冲区中已有,就可能直接从缓冲区中读取。如果没有,就从文件中读取,并将其加入至缓冲池中。如果缓冲池已满,根据一定的算法淘汰旧的缓冲区,如LRU算法等。

#26


你这种非结构化的数据通常使用数据库的效率反而不会高。

#27


shit~~~~~

这么过分的要求,哪你就一次把文件的所有数据读到内存里面去计算。
反正现在内存夜便宜

#28


哈哈,好办法。听说2G的内存条已研制出来了...

#29


为什么这么好的办法Kevin先想到?!!!!!!

#30


嘿嘿嘿

#31


自己设计一个数据库格式, 自己字节进行压缩....

#32


嘿嘿嘿 
   ————真黑!

#33


up

#34


up

#35


用文件映射
所谓文件映射不是把文件全读进来,而是由操作系统来帮你做缓冲,和换页算法。这东西很适合随机读大文件。优点如下:
1方便,不需复杂编程
2可以利用空闲的内存,内存不必非常大,但加一点就好一点。
3有顺序地址的访问,你可以在原有的文件外部建立索引,或什么东西来加速读取

此外,我想从数据本身的特性来入手是最有效的。

编码如下:
HANDLE m_File = ::(strPathname,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL)
HANDLE m_FileMap = ::CreateFileMapping(
(void*)0xFFFFFFFF,
NULL,
PAGE_READ,
0,1024,
NULL
);
ASSERT(m_FileMap != NULL);
if(GetLastError() == ERROR_ALREADY_EXISTS){
TRACE("the share memory has already existed!\n");
}
else{
TRACE("Create share memory\n");
}
void* m_pMapMem = (char*)::MapViewOfFile(this->m_FileMap,FILE_MAP_READ,0,0,0);
ASSERT(m_pMapMem != NULL);
//..............use it......................//
UnmapViewOfFile(m_pMapMem);
CloseHandle(m_File);
CloseHandle(m_FILEMap);

#36


参考一下硬盘的数据读取技术

#37


不好意思,小弟真是没办法了,老板下星期就
要我交任务,问题贴出来已经两个星期了,就是找不到答案,
所以真是sorry了,在这占用你们的空间,希望能给小弟一个答复!先谢谢了!!

我以CEditView为基类建了一个MDI(其他什么代码我也没写),
有如下要求:我打开一个*.asm文档,想在光标所在行设一个断点,
要达到如在bc设断点的效果,在VC怎么做?能详细点回答吗?
有例子给我就感激不尽了!!
或转到http://www.csdn.net/expert/topic/171/171611.shtm

本人邮箱:wrongt@163.com

#38


以前也做过类似的三维项目,我们是将数据分成基本图形类,然后再内存中以指针连表(用CList)管理。
保存时可在CDocument::Serialize()中直接对CList调用序列化函数。对文件时再恢复成指针连表CList使用。速度不慢。不过你必须为你的C3dPoint,CLine,CCircle等基本图形类添加Serialize()函数,而且必须由CObject派生,这样调用CList:Serialize时MFC会自动去调用这些基本图形类的Serialize().