• Delphi 高效处理大数据量的字典数据的查询问题


    一、需求

    系统中存在基本字典数据,且数据量大,需要根据各种条件查询某个字典数据,该如何高效实现?

    例如:系统中的菜品字典数据,需要根据菜品ID、菜品编码、菜品名+菜品规格等条件查找菜品

    二、思路

    1、使用索引的方法

    将每个查询条件都建立一个TStringList,并添加条件值,并确保其与菜品对象 TMenuItem 在TList中的位置一样。 查询时,根据条件值找到TStringList中的位置 index,然后直接通过TList[index] 获取菜品对象。

    该方法查询时不用遍历整个 TList ,从而提高查询效率。

    2、使用哈希方法

    将每个查询条件添加到 TDictionary 字典 TFMenuItemHash(TDictionary),Key 值为 【条件前缀+菜品对应ID等值】,Value 值为 TMenu 对象地址。查询时,通过FMenuItemHash.TryGetValue 获取。

    注意:程序结束时,需要遍历 TFMenuItemHash,释放 TFMenuItemHash 对应的 TMenu 对象

    三、代码实现

    这里只展示思路2对应的代码实现。

    1. unit uMenuItem;
    2. interface
    3. uses
    4. Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
    5. System.Classes, System.Generics.Collections;
    6. //定义查询条件类型 按菜品ID 菜品Key 菜品编码 菜品名称 菜品名称+规格 菜品ID+规格
    7. type
    8. TMenuItemListType = (mltID, mltKey, mltCode, mltName, mltNameUnit, mltIDUnit, mltKeyUnit);
    9. const
    10. MenuItemListTypeArry: array [TMenuItemListType] of string = ('mltID', 'mltKey', 'mltCode', 'mltName', 'mltNameUnit', 'mltIDUnit', 'mltKeyUnit');
    11. type
    12. //菜品类
    13. TMenuItem = class
    14. //...菜品ID、菜品名等属性
    15. end;
    16. //菜品字典列表类
    17. TMenuItemLst = class
    18. private
    19. FMenuItemHash: TDictionary<string, TMenuItem>;
    20. //添加Key值到 FMenuItemHash 中
    21. procedure AddMenuItem(MenuItemType: TMenuItemListType; AKey: string; AMenuItem: TMenuItem);
    22. //从 FMenuItemHash 中获取 key 值对应的 TMenuItem 对象
    23. function GetMenuItem(MenuItemType: TMenuItemListType; AKey: string): TMenuItem;
    24. function InitData(): boolean;
    25. function GetCount: integer;
    26. function GetItems(Index: integer): TMenuItem;
    27. protected
    28. FList: TList;
    29. public
    30. constructor Create(); overload;
    31. destructor Destroy; override;
    32. property Count: integer read GetCount;
    33. property Items[Index: integer]: TMenuItem read GetItems; default;
    34. procedure Clear;
    35. procedure ClearFoodCannotSaleList;
    36. procedure Delete(iIndex: integer);
    37. function IndexOf(AMenuItem: TMenuItem): integer;
    38. function Refresh(): Boolean;
    39. //按菜品ID查询
    40. function GetMenuItemByFoodID(AFoodID: int64): TMenuItem;
    41. //按菜品规格查询
    42. function GetMenuItemByUnitKey(AUnitKey: string): TMenuItem;
    43. //按菜品编码查询
    44. function GetMenuItemByFoodCode(AFoodCode: string): TMenuItem;
    45. //按菜品名称查询
    46. function GetMenuItemByFoodName(AFoodName: string): TMenuItem;
    47. //按菜品名称+规格查询
    48. function GetMenuItemByFoodNameUnit(AFoodName, AFoodUnit: string): TMenuItem;
    49. //按菜品ID+规格查询
    50. function GetMenuItemByFoodIDUnit(AFoodID: int64; AFoodUnit: string): TMenuItem;
    51. //按菜品Key+规格查询
    52. function GetMenuItemByFoodKeyUnit(AFoodKey, AFoodUnit: string): TMenuItem;
    53. end;
    54. implementation
    55. { TMenuItemLst }
    56. procedure TMenuItemLst.Clear;
    57. var
    58. i: integer;
    59. begin
    60. for i := 0 to FList.Count - 1 do
    61. begin
    62. FList[i].Free;
    63. end;
    64. FList.Clear;
    65. FMenuItemHash.Clear;
    66. end;
    67. constructor TMenuItemLst.Create;
    68. begin
    69. FList := TList.Create;
    70. FMenuItemHash := TDictionary<string, TMenuItem>.Create;
    71. end;
    72. procedure TMenuItemLst.Delete(iIndex: integer);
    73. begin
    74. TMenuItem(FList[iIndex]).Free;
    75. FList.Delete(iIndex);
    76. end;
    77. destructor TMenuItemLst.Destroy;
    78. begin
    79. Clear;
    80. FList.Free;
    81. FMenuItemHash.Free;
    82. inherited;
    83. end;
    84. function TMenuItemLst.GetCount: integer;
    85. begin
    86. Result := FList.Count;
    87. end;
    88. procedure TMenuItemLst.AddMenuItem(MenuItemType: TMenuItemListType;
    89. AKey: string; AMenuItem: TMenuItem);
    90. begin
    91. FMenuItemHash.AddOrSetValue(MenuItemListTypeArry[MenuItemType] + AKey, AMenuItem);
    92. end;
    93. function TMenuItemLst.GetMenuItem(MenuItemType: TMenuItemListType;
    94. AKey: string): TMenuItem;
    95. begin
    96. FMenuItemHash.TryGetValue(MenuItemListTypeArry[MenuItemType] + AKey, Result);
    97. end;
    98. function TMenuItemLst.GetItems(Index: integer): TMenuItem;
    99. begin
    100. Result := nil;
    101. if (Index >= 0) and (Index < FList.Count) then
    102. Result := TMenuItem(FList[Index]);
    103. end;
    104. function TMenuItemLst.GetMenuItemByFoodCode(AFoodCode: string): TMenuItem;
    105. begin
    106. Result := GetMenuItem(mltCode, AFoodCode);
    107. end;
    108. function TMenuItemLst.GetMenuItemByFoodID(AFoodID: int64): TMenuItem;
    109. begin
    110. Result := GetMenuItem(mltID, AFoodID.ToString);
    111. end;
    112. function TMenuItemLst.GetMenuItemByFoodIDUnit(AFoodID: int64;
    113. AFoodUnit: string): TMenuItem;
    114. begin
    115. Result := GetMenuItem(mltIDUnit, AFoodID.ToString + AFoodUnit);
    116. end;
    117. function TMenuItemLst.GetMenuItemByFoodKeyUnit(AFoodKey,
    118. AFoodUnit: string): TMenuItem;
    119. begin
    120. Result := GetMenuItem(mltKeyUnit, AFoodKey + AFoodUnit);
    121. end;
    122. function TMenuItemLst.GetMenuItemByFoodName(AFoodName: string): TMenuItem;
    123. begin
    124. Result := GetMenuItem(mltName, AFoodName);
    125. end;
    126. function TMenuItemLst.GetMenuItemByFoodNameUnit(AFoodName,
    127. AFoodUnit: string): TMenuItem;
    128. begin
    129. Result := GetMenuItem(mltNameUnit, AFoodName + AFoodUnit);
    130. end;
    131. function TMenuItemLst.GetMenuItemByUnitKey(AUnitKey: string): TMenuItem;
    132. begin
    133. Result := GetMenuItem(mltKey, AUnitKey);
    134. end;
    135. function TMenuItemLst.IndexOf(AMenuItem: TMenuItem): integer;
    136. begin
    137. Result := FList.IndexOf(AmenuItem);
    138. end;
    139. function TMenuItemLst.InitData(): boolean;
    140. var
    141. i: integer;
    142. menuItem: TMenuItem;
    143. foodID, foodUnitKey, foodCode, foodName, foodUnit: string;
    144. begin
    145. result := false;
    146. try
    147. try
    148. //循环数据集, 假如已从数据库中查询了所有菜品字典数据
    149. for i := 0 to 10000 do
    150. begin
    151. //初始化菜品对象,在 TMenuItemLst 类释放时,需要循环释放 TMenuItem
    152. menuItem := TMenuItem.Create();
    153. foodID := menuItem.FoodID;
    154. foodUnitKey := menuItem.FoodUnitKey;
    155. foodCode := menuItem.FoodCode;
    156. foodName := menuItem.FoodName;
    157. foodUnit := menuItem.FoodUnit;
    158. if foodID <> '' then //添加菜品ID的Key值
    159. AddMenuItem(mltID, foodID, menuItem);
    160. if foodUnitKey <> '' then //添加菜品Key的Key值
    161. AddMenuItem(mltKey, foodUnitKey, menuItem);
    162. if FoodCode <> '' then //添加菜品编码的Key值
    163. AddMenuItem(mltCode, foodCode, menuItem);
    164. if foodName <> '' then
    165. AddMenuItem(mltName, foodName, menuItem);
    166. if (foodName <> '') or (foodUnit <> '') then
    167. AddMenuItem(mltNameUnit, foodName + foodUnit, menuItem);
    168. if (foodID <> '') or (foodUnit <> '') then
    169. AddMenuItem(mltIDUnit, foodID + foodUnit, menuItem);
    170. if (foodUnitKey <> '') or (foodUnit <> '') then
    171. AddMenuItem(mltKeyUnit, foodUnitKey + foodUnit, menuItem);
    172. FList.Add(menuItem);
    173. end;
    174. result := true;
    175. except
    176. on E: Exception do
    177. begin
    178. raise Exception.Create(E.Message);
    179. end;
    180. end;
    181. finally
    182. end;
    183. end;
    184. function TMenuItemLst.Refresh(): Boolean;
    185. begin
    186. end;
    187. end.

  • 相关阅读:
    通过语言模型奖励实现视频大型多模态模型的直接偏好优化
    【Python毕业设计源码】django个性化服装系统
    联合关系抽取论文(一)——TPLinker
    IT入门知识第七部分《移动开发》(7/10)
    MySQL、高级SQL操作
    【LeetCode】【Java】有效的数组
    UE5第一人称射击游戏蓝图教程
    刷代码随想录有感(46):平衡二叉树
    Python3 基础语法
    网络层(IP数据报格式、ARP协议)
  • 原文地址:https://blog.csdn.net/longchanghua_enshi/article/details/138622688