SQL 查询速度快,但结果检索速度慢
我正在使用 Sybase 的 Advantage 数据库服务器,目前有一个很好的快速左连接查询,运行速度非常快。问题是运行查询后我想将结果放入字符串中。我检索了包含 55000 个条目的数据集。 现在最多需要 16 秒。将其放入字符串中。我的查询只花了 8 毫秒运行。我的第一次尝试是这样的:
aADSQuery.Open
aADSQuery.First
WHILE not aADSQuery.eof do
begin
s := s + aADSQuery.FieldbyName('Name').asString+',';
aADSQuery.Next;
end;
之后,我尝试这样做以避免 aADSQuery.next,但是 aADSQuery.RecordCount 占用了 我9秒
aADSQuery.Open
aADSQuery.First
Count := aADSQuery.RecordCount;
for i:=0 to count-1 do
begin
aADSQuery.RecNo := i;
aADSQuery.FieldbyName('Name').AsString;
end;
数据库已建立索引,主键为条目 ID,索引为其他列。 我考虑过创建一个视图来计算我的条目以避免记录计数,这可能与 sql 计数完全相同。但视图中的条目计数所花费的时间与以前相同。如果我使用sql 算一下我的基表有 130000 个条目,只需要 200 毫秒。但是,如果我在不使用视图的情况下对结果表进行计数,则需要 9 秒。我想是的,因为新的临时结果表没有索引。有谁知道如何以正确的方式处理此类问题或如何获得更快的结果计数?
非常感谢
I am using the Advantage Database Server from Sybase and have for the moment a nice fast left join query, that runs really fast. The problem is that after running the query I would like to put the results into a string. I retrieved a dataset of 55000 entries.
Now It takes up to 16 sec. to put it into the string. My query only took 8 ms to run. My first atempt was this:
aADSQuery.Open
aADSQuery.First
WHILE not aADSQuery.eof do
begin
s := s + aADSQuery.FieldbyName('Name').asString+',';
aADSQuery.Next;
end;
After, I tried this to avoid the aADSQuery.next, but the aADSQuery.RecordCount took
me 9 sec.
aADSQuery.Open
aADSQuery.First
Count := aADSQuery.RecordCount;
for i:=0 to count-1 do
begin
aADSQuery.RecNo := i;
aADSQuery.FieldbyName('Name').AsString;
end;
The database is indexed, with primary key for the Entry ID and indizes for the other columns.
I thought about creating a view to count my entries to avoid the recordcount, that might exactly do the same than the sql count. But the count of the entries from the view took the same time as before. If I use the sql
count on my base table with 130000 entries it takes only 200 ms. But if I am doing a count on my resulting table, without using a view it takes me 9 s. I quess it is, because there are no indizes for the new temporary result table. Does anyone know how to handle this kind of problem in a proper way or how to get a faster result count?
Thank you very much
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
使用一些基于缓冲区的类(例如 TStringStream)来填充字符串。这将避免
String
连接 (s := s + foo
) 的缓慢重新分配。不要在循环中使用
aADSQuery.FieldbyName('Name').AsString
。很慢。相反,创建一个局部变量
F
,如下所示:我相信使用
aADSQuery.Next
比使用RecNo
更快您可以在服务器端生成该字符串并将其返回到客户端,而无需在客户端构造任何字符串:
您还可以通过设置
TAdsQuery.AdsTableOptions
。确保将AdsFilterOptions
设置为IGNORE_WHEN_COUNTING
,并将AdsFreshRecordCount
设置为False
。Use some buffer based class such as
TStringStream
to populate the string. this will avoid slow reallocation ofString
concatenation (s := s + foo
).Don't use
aADSQuery.FieldbyName('Name').AsString
in the loop. It's slow.Instead create a local variable
F
like this:I believe using
aADSQuery.Next
is faster than usingRecNo
You can generate that string on the server side and return it to the client side without the need to construct any strings on the client side:
Also you could optimize performance by setting
TAdsQuery.AdsTableOptions
. Make sureAdsFilterOptions
is set toIGNORE_WHEN_COUNTING
andAdsFreshRecordCount
is set toFalse
.从OP来看,我并不完全清楚目标是查找记录总数还是向用户显示数据。如果要显示数据,那么将 55,000 条记录的所有数据附加到单个字符串中可能不是最好的方法。如果您对 Advantage Data Architect 中运行查询的性能感到满意,那么使用类似的方法并将数据存储在某种网格中可能是有意义的。
例如,将 TDataSource 与 TDBGrid 关联并将查询绑定到数据源:
数据感知网格将仅获取填充网格所需的数据,并在用户翻阅网格时按需请求数据。
编辑 当您请求记录计数时,服务器必须解析整个结果集。如果您使用 Advantage Local Server 并且数据驻留在网络服务器上,则通过网络读取所有数据将产生额外成本。如果您使用 Advantage Database Server(客户端/服务器版本),则处理将在服务器上进行,并且速度可能会快得多。
这当然取决于查询,但解析结果集的 9 秒可能太长了。在 Advantage Data Architect 中,您可以检查查询的优化情况。 SQL 菜单下有一个“显示计划”选项,SQL 实用程序的工具栏上有一个用于显示查询计划的按钮。可能您缺少必要的索引。
From the OP, it is not entirely clear to me if the goal is to find the total number of records or to display the data to a user. If it is to display the data, then appending all the data for 55,000 records into a single string is probably not the best approach. If you are happy with the performance of running the query in Advantage Data Architect, then it probably makes sense to use the similar approach and store the data in some kind of grid.
For example, associate a TDataSource with a TDBGrid and bind the query to the data source:
The data aware grid will only fetch as much data as is needed to fill the grid and will request data on demand as the user pages through it.
Edit When you request the record count, the entire result set has to be resolved by the server. If you are using Advantage Local Server and if the data resides on a network server, then there will be extra cost involved in reading all of the data across the network. If you are using Advantage Database Server (the client/server version), then the processing will take place at the server and may be much faster.
It of course depends on the query, but 9 seconds to resolve the result set might be overly long. Within Advantage Data Architect, you can check the optimization of the query. There is a "Show Plan" option under the SQL menu as well as a button on the tool bar in the SQL utility for showing the query plan. It may be that you are missing a necessary index.
为什么不在服务器端执行您需要的操作并返回结果呢?
而且在这样的情况下:
Why dont't you perform what you need server side and just return the result?
Moreover in situation like this:
最后,我发现了我的错误,但有些事情我不明白。
首先,我在连接查询中更改了左连接 sql 查询。这使得我的记录计数更快,而且如果我使用 next,现在速度更快。之后我检查了每一列的表类型。我发现,如果没有必要,对字符列使用固定大小的性能不是很好。在我的例子中,我为 20 列选择了 100 的大小,但我的列的大小以 3 为步长从第 1 列增加到第 20 列。因此,第 20 列的最大大小为 60,第 1 列有 3 个字符。(这些是我的搜索列)这使得我的 while do 子句速度提高了两倍。随着这些变化。我可以在 5500 毫秒内获取 55000 个条目。现在我改变了桌子的设计。我已将所有内容放在一张表中,不再需要连接。至少目前还不行。我使用了普通的 Select .. From ..Where 子句。我处理这 55000 个条目结果的时间再次减少到 2500 毫秒。这对我来说再好不过了。
所以唯一的问题仍然是,如果我使用不同的 SQL 查询,为什么在执行 ADSQuery.open 后获取数据会产生很大的差异。我认为这可能会影响sql查询的执行时间,但它也影响了
结果获取。
So finally, I've found my mistakes, but some things i don't understand.
First of all I changed my left join sql query inside a join query. That made my recordcount faster and also if I am using next,it is faster now. So after that I've checked my table types for each column. And I found out,that it's not very performant to use a fixed size for a character column if it is not necessary. In my case I've choosen a size of 100 for 20 columns, but my columns are increasing in size from column 1 to 20 in steps of three. So the maximum size of column 20 is 60 and column 1 has 3 characters.(These are my search columns) That made my while do clause already two times faster. With these changes. I could get my 55000 entries in 5500 ms. Now I changed the table design. I've put everything in one table, that I don't need a join anymore. At least not for the moment. I used a normal Select .. From .. Where clause. My time for these 55000 entry results was reduced again to 2500 ms. That's more than fine for me.
So the only question is still, why it makes a big difference in fetching the data after performing the ADSQuery.open ,if I am using a different sql query. I thought it might affect the time of the execution of the sql query, but it is also affecting the
result fetching.