In this article, I will conduct a comparative analysis of DataSet'ov, which keep the data in memory.
List of DataSets
- TJvMemoryData
Developer: JEDI Visual Component Library (JCL + JVCL) Community
JCL (version 2.8)
JVCL (version 3.50)
β Official website - TMemTableEh
Developer: EhLib
Version: 9.0.040
β Official website - TdxMemData
Developer: DevExpress
Version: 15.2.2
β Official website - TkbmMemTable
Developers: Components4Developers
Version: 7.74.00 Professional Edition
β Official website
DataSet comparison options
- Insert records
- Sort records
Environment
Delphi | 10.2 Tokyo Starter |
operating system | Windows 7 SP1 Ultimate x64 |
CPU | Intel Core i5 |
Ram | 8 GB |
Test data
DataSets will be tested on data obtained from the Firebird database. For comparative analysis, I created 100,000 records in the database with different data types:
β’ whole numbers;
β’ real numbers;
β’ dates;
β’ lines;
β’ Images.
Comparison
- Data loading
Dataset | LoadFromDataSet | Manual | The average |
---|
TJvMemoryData | 7.7846 sec | 5,7500 seconds | 6.7673 sec |
TMemTableEh | 4,5114 sec | 7.2978 sec | 5.9046 sec |
TdxMemData | 6.3804 sec | 6.5082 sec | 6.4443 sec |
TkbmMemTable | 5.4474 sec | 6.0562 sec | 5.7518 sec |
The loads for each DataSet were performed 5 times, the arithmetic average was calculated from the obtained values. The average value is the arithmetic average of the load values ββusing the LoadFromDataSet method and the manual load value.
')
Results:
TMemTableEh - the fastest data load using the LoadFromDataSet method
TJvMemoryData - the fastest manual data download
TkbmMemTable - the fastest average data load
Time measurement source codevar start_time, end_time, total_time: double; start_time := GetTickCount; ... end_time := GetTickCount; total_time := (end_time - start_time) / 1000;
Load data source code LoadFromDataSet //TJvMemoryData //function LoadFromDataSet(Source: TDataSet; RecordCount: Integer; Mode: TLoadMode; DisableAllControls: Boolean = True): Integer; JvMemoryData.LoadFromDataSet(FIBDataSet, -1, lmCopy); //TMemTableEh //function LoadFromDataSet(Source: TDataSet; RecordCount: Integer; Mode: TLoadMode; UseCachedUpdates: Boolean): Integer; MemTableEh.LoadFromDataSet(FIBDataSet, -1, lmCopy, true); //TdxMemData //procedure LoadFromDataSet(DataSet : TDataSet); dxMemData.LoadFromDataSet(FIBDataSet); //TkbmMemTable //procedure TkbmCustomMemTable.LoadFromDataSet(Source:TDataSet; CopyOptions:TkbmMemTableCopyTableOptions; Mapping:string=''); kbmMemTable.LoadFromDataSet(FIBDataSet, [mtcpoAppend]);
Manual source code while not FIBDataSet.Eof do begin table.Append; table.FieldByName('ID').AsInteger := FIBDataSet.FieldByName('ID').AsInteger; table.FieldByName('SUMM').AsFloat := FIBDataSet.FieldByName('SUMM').AsFloat; table.FieldByName('COMMENT').AsString := FIBDataSet.FieldByName('COMMENT').AsString; ... table.Post; FIBDataSet.Next; end; table.First;
TJvMemoryData is the only DataSet whose manual loading of data turned out to be faster than loading using the LoadFromDataSet method.
TdxMemData is the only DataSet that, after loading data using the LoadFromDataSet method, does not return a position in the DataSet to the first record. - Sorting
Dataset | Integer | Real number | Line | The average |
---|
TJvMemoryData | 0.3492 sec | 0.8330 sec | 1,9938 sec | 1,0587 sec |
TMemTableEh | 0.9014 sec | 0.8642 sec | 3.6876 sec | 1.8177 sec |
TdxMemData | 0,3616 s | 0.3650 sec | 0.9134 sec | 0.5467 sec |
TkbmMemTable | 0.1996 sec | 0.2186 sec | 0.7550 sec | 0.3897 sec |
Sorting for each DataSet'a was performed 5 times, the arithmetic average was calculated from the obtained values. The average value is the arithmetic average of the sort values.
Results:
TkbmMemTable - the fastest sorting of integers
TkbmMemTable - the fastest sorting of real numbers
TkbmMemTable - the fastest sorting of lines
TkbmMemTable - the fastest average sorting
Time measurement source code var start_time, end_time, total_time: double; start_time := GetTickCount; ... end_time := GetTickCount; total_time := (end_time - start_time) / 1000;
Source code for sorting data //TJvMemoryData //procedure SortOnFields(const FieldNames: string = ''; CaseInsensitive: Boolean = True; Descending: Boolean = False); JvMemoryData.SortOnFields(fields, false, false); //TMemTableEh //procedure SortByFields(const SortByStr: string); MemTableEh.SortByFields(fields); //TdxMemData dxMemData.SortedField := fields; //TkbmMemTable //procedure SortOn(const FieldNames:string; Options:TkbmMemTableCompareOptions); kbmMemTable.SortOn(fields, []);
I note that only for the TMemTableEh DataSet when sorting by several fields you can set a different sorting direction for each field (ascending / descending).
Conclusion
The undisputed leader was the DataSet
TkbmMemTable , but all the other DataSets showed good results. But you can use TkbmMemTable only with Delphi XE2.
Of course, it is unlikely that you need to load 100,000 records on real data for display to the user. Also, when choosing a DataSet, it is necessary to take into account that on a different data set (for example, in the absence of downloading images or for an x64 application), the results of the speed of work may be different. In addition, many DataSets have additional functionality for working with a grid from their library.
More about TMemTableEh
The TMemTableEh component appeared in EhLib 4.0. All library components, including TMemTableEh, have been running since Delphi 7.
The advantages of using MemTableEh compared to other DataSets are the following:
- It supports a special interface that allows the DBGridEh component to view all data without moving the active record.
- Allows you to upload data from a TDataDriverEh object (DataDriver property).
- Allows you to upload changes back to DataDriver, promptly or deferred (depending on the properties of CachedUpdates).
- Allows you to create a master / client relationship on the client (by filtering records) or on an external source (by updating the [Params] parameters and re-querying the details with DetailDataDriver).
- Allows you to sort data, including Calculated and Lookup fields.
- Allows you to create and fill in data in design-time and save the data in a dfm-file form.
- Allows you to store records in the form of a tree. Each record can have node / branch records and itself be a node of another parent record. The TDBGridEh component supports the display functionality of the tree structure of these records.
- Allows you to connect to the internal array of another TMemTableEh component (ExternalMemData property) and work with its data: sort, filter, edit.
- It has an interface for getting a list of all column values, ignoring the local DataSet filter. TDBGridEh uses this property to automatically generate a list in the dropdown dropdown filter.
About TRxMemoryData
Development: RxLib
The TRxMemoryData component appeared in version RxLib 2.60.
The DataSet TRxMemoryData does not participate in the comparison, because in 2002 the RxLib library was officially incorporated into the JVCL. JVCL has a utility for quickly replacing all Rx components, functions and units on the JVCL version.
Why go to JVCL:
Unlike RxLib, JVCL is evolving. Errors are corrected. Regularly released version with support for new versions of Delphi. JVCL components support newer versions of Windows and Windows styles.
How do I use DataSets in my practice?
- TRxMemoryData
- TMemTableEh
- TRxMemoryData
- TJvMemoryData
- TkbmMemTable