sqlite采用UUID主键和int型自增主键性能对比测试

论坛 期权论坛 脚本     
已经匿名di用户   2022-7-2 21:58   1372   0


最近在工作中,遇到到了sqlite主键类型选择的问题,于是就做个测试程序来测试sqlite采用UUID主键和int型自增主键性能对比。(本人时间有限,没有做多次测试,希望有人能帮着多测试一下)

1.sqlite采用UUID主键的优点和缺点。

优点:安卓端sqlite表的主键和服务器端数据库表的主键可以保持一致,不用做复杂的业务处理,开发效率高;数据安全性较好,用户无法从id估算该表的数据量。
缺点:UUID字符串长度太长,加大网络数据传输数据量。

2.sqlite采用int型自增主键的优点和缺点。

优点:int型主键字符串长度短,网络传输数据量不大。
缺点:安卓端sqlite表的主键与服务器端数据库表的主键不可能一致,需要做复杂的业务处理,开发效率低;做表关联需要insert后返回主键值的时候需要多一次select max(id)的操作。

3.测试环境

测试手机三星Galaxy S3(i9300)
安卓版本Android 4.3 (CM10.2)
软件环境已ROOT,杀掉全部后台服务
测试用例sqlite表结构
UUID主键:
[sql]
  1. create table sysUserUUID (id TEXT PRIMARY KEY , uName TEXT )
int自增主键:
[sql]
  1. create table sysUserInt (id INTEGER PRIMARY KEY AUTOINCREMENT, uName TEXT )

转换json工具包:gson-2.2.4.jar

4.测试结果

操作UUID主键int自增主键
插入数据耗时100条1582ms1583ms
500条10308ms9496ms
读取数据耗时100条19ms25ms
500条58ms59ms
json字符串大小100条6.14kb2.62kb
500条31.14kb13.95kb


5. 结论

根据测试数据我们可以得出以下结论:
1.sqlite只是简单的文件型数据库,没有对任何类型的主键进行优化,所以采用UUID和int自增主键没有本质上的性能差距,而我们测试中UUID比int主键稍微慢一点的原因我认为是uuid字符串太长。
2.用json传输数据时,每100条uuid的数据会比int型的大3.4kb左右,考虑到本测试中int型主键都是从1开始的,而实际应用中可能大于10000,故而他们的差距应该比3.4kb要小;如果再考虑做表关联时需要传输复合主键,那么int型的大小应该再大一些。考虑到一般读取数据不会超过100条,这个差距即使在2G的网络环境下对响应时间的影响也不到0.5秒。故而数据大小的区别可以忽略。

6. 附:主要测试类

[java]
  1. package com.zf.uuidtest;
  2. import java.io.File;
  3. import java.util.ArrayList;
  4. import java.util.Date;
  5. import java.util.List;
  6. import java.util.UUID;
  7. import javax.crypto.interfaces.PBEKey;
  8. import com.example.uuidtest.R;
  9. import com.google.gson.Gson;
  10. import android.os.Bundle;
  11. import android.os.Environment;
  12. import android.os.Handler;
  13. import android.app.Activity;
  14. import android.app.ProgressDialog;
  15. import android.database.Cursor;
  16. import android.database.sqlite.SQLiteDatabase;
  17. import android.database.sqlite.SQLiteOpenHelper;
  18. import android.util.Log;
  19. import android.view.Menu;
  20. import android.view.View;
  21. import android.view.View.OnClickListener;
  22. import android.widget.Button;
  23. import android.widget.EditText;
  24. import android.widget.ProgressBar;
  25. import android.widget.TextView;
  26. import android.widget.Toast;
  27. public class MainActivity extends Activity {
  28. TextView tvUUIDTitle;
  29. TextView tvIntTitle;
  30. EditText etTestIntCount;
  31. EditText etTestUUIDCount;
  32. Button btnStartTestUUID;
  33. Button btnStartTestInt;
  34. TextView tvUUIDRs;
  35. TextView tvIntRs;
  36. ProgressBar pbInProgress;
  37. Button btnStartLoadTestUUID;
  38. Button btnStartLoadTestInt;
  39. int intTestCnt;
  40. int UUIDTestCnt;
  41. long intTestCost;
  42. long UUIDTestCost;
  43. File UUIDFile;
  44. File intFile;
  45. DatabaseUtil db;
  46. static final int TEST_INT_MSG = 11110;
  47. static final int LOAD_INT_MSG = 41110;
  48. static final int TEST_UUID_MSG = 11111;
  49. static final int LOAD_UUID_MSG = 41111;
  50. static final int DONE_CNT_MSG = 21111;
  51. static String APP_DIR = "test_sqlite";
  52. int doneCnt;
  53. List<SysUserUUID> sysUserUUIDs;
  54. List<SysUserInt> sysUserInts;
  55. @Override
  56. protected void onCreate(Bundle savedInstanceState) {
  57. super.onCreate(savedInstanceState);
  58. setContentView(R.layout.activity_main);
  59. db = new DatabaseUtil(this);
  60. db = db.open();
  61. db.executeSql("drop table if exists sysUserInt");
  62. db.executeSql("drop table if exists sysUserUUID");
  63. db.executeSql("create table sysUserInt (id INTEGER PRIMARY KEY AUTOINCREMENT, uName TEXT )");
  64. db.executeSql("create table sysUserUUID (id TEXT PRIMARY KEY , uName TEXT )");
  65. initView();
  66. }
  67. Handler handler = new Handler() {
  68. public void handleMessage(android.os.Message msg) {
  69. pbInProgress.setVisibility(View.GONE);
  70. switch (msg.what) {
  71. case DONE_CNT_MSG:
  72. break;
  73. case TEST_INT_MSG:
  74. String intRs = "插入耗时 " + intTestCost + "ms";
  75. tvIntRs.setText(intRs);
  76. btnStartLoadTestInt.setEnabled(true);
  77. break;
  78. case TEST_UUID_MSG:
  79. String uuidRs = "插入耗时 " + UUIDTestCost + "ms";
  80. tvUUIDRs.setText(uuidRs);
  81. btnStartLoadTestUUID.setEnabled(true);
  82. break;
  83. case LOAD_INT_MSG:
  84. String rs1 = tvIntRs.getText().toString() + ", 读取耗时 "
  85. + intLoadCost + "ms, json文件大小"+FileUtils.getFormatSize(intFile.length());
  86. tvIntRs.setText(rs1);
  87. break;
  88. case LOAD_UUID_MSG:
  89. String rs = tvUUIDRs.getText().toString() + ", 读取耗时 "
  90. + UUIDLoadCost + "ms, json文件大小"+FileUtils.getFormatSize(UUIDFile.length());
  91. tvUUIDRs.setText(rs);
  92. break;
  93. default:
  94. break;
  95. }
  96. };
  97. };
  98. void initView() {
  99. tvUUIDTitle = (TextView) findViewById(R.id.tvUUIDTitle);
  100. tvIntTitle = (TextView) findViewById(R.id.tvIntTitle);
  101. etTestIntCount = (EditText) findViewById(R.id.etTestIntCount);
  102. etTestUUIDCount = (EditText) findViewById(R.id.etTestUUIDCount);
  103. tvUUIDRs = (TextView) findViewById(R.id.tvUUIDRs);
  104. tvIntRs = (TextView) findViewById(R.id.tvIntRs);
  105. btnStartTestUUID = (Button) findViewById(R.id.btnStartTestUUID);
  106. btnStartTestInt = (Button) findViewById(R.id.btnStartTestInt);
  107. btnStartLoadTestUUID = (Button) findViewById(R.id.btnStartLoadTestUUID);
  108. btnStartLoadTestInt = (Button) findViewById(R.id.btnStartLoadTestInt);
  109. pbInProgress = (ProgressBar) findViewById(R.id.pbInProgress);
  110. btnStartTestInt.setOnClickListener(new OnClickListener() {
  111. @Override
  112. public void onClick(View v) {
  113. pbInProgress.setVisibility(View.VISIBLE);
  114. intTestCnt = Integer.parseInt(etTestIntCount.getText()
  115. .toString());
  116. new Thread() {
  117. public void run() {
  118. try {
  119. long start = new Date().getTime();
  120. for (int i = 0; i < intTestCnt; i++) {
  121. StringBuilder sb = new StringBuilder(
  122. "insert into sysUserInt (uName) values ('")
  123. .append("name").append(i).append("')");
  124. db.executeSql(sb.toString());
  125. }
  126. long end = new Date().getTime();
  127. intTestCost = end - start;
  128. handler.sendEmptyMessage(TEST_INT_MSG);
  129. } catch (Exception ex) {
  130. ex.printStackTrace();
  131. }
  132. };
  133. }.start();
  134. }
  135. });
  136. btnStartTestUUID.setOnClickListener(new OnClickListener() {
  137. @Override
  138. public void onClick(View v) {
  139. pbInProgress.setVisibility(View.VISIBLE);
  140. UUIDTestCnt = Integer.parseInt(etTestUUIDCount.getText()
  141. .toString());
  142. new Thread() {
  143. public void run() {
  144. try {
  145. long start = new Date().getTime();
  146. for (int i = 0; i < UUIDTestCnt; i++) {
  147. StringBuilder sb = new StringBuilder(
  148. "insert into sysUserUUID (id,uName) values ('")
  149. .append(UUID.randomUUID())
  150. .append("','").append("name").append(i)
  151. .append("')");
  152. db.executeSql(sb.toString());
  153. }
  154. long end = new Date().getTime();
  155. UUIDTestCost = end - start;
  156. handler.sendEmptyMessage(TEST_UUID_MSG);
  157. } catch (Exception ex) {
  158. ex.printStackTrace();
  159. }
  160. };
  161. }.start();
  162. }
  163. });
  164. btnStartLoadTestUUID.setOnClickListener(new OnClickListener() {
  165. @Override
  166. public void onClick(View arg0) {
  167. pbInProgress.setVisibility(View.VISIBLE);
  168. UUIDTestCnt = Integer.parseInt(etTestUUIDCount.getText()
  169. .toString());
  170. new Thread() {
  171. public void run() {
  172. try {
  173. long start = new Date().getTime();
  174. String sql = "select * from sysUserUUID order by id limit "
  175. + UUIDTestCnt + " offset 0 ";
  176. Cursor cr = db.mDb.query("sysUserUUID",
  177. new String[] { "id", "uName" }, null, null,
  178. null, null, " id limit " + UUIDTestCnt
  179. + " offset 0 ");
  180. sysUserUUIDs = new ArrayList<SysUserUUID>();
  181. while (cr.moveToNext()) {
  182. SysUserUUID sysUserUUID = new SysUserUUID();
  183. sysUserUUID.setId(cr.getString(0));
  184. sysUserUUID.setuName(cr.getString(1));
  185. sysUserUUIDs.add(sysUserUUID);
  186. }
  187. if (Environment.getExternalStorageState().equals(
  188. Environment.MEDIA_MOUNTED)) {
  189. String dirStr = Environment
  190. .getExternalStorageDirectory()
  191. .getPath()
  192. + File.separator + APP_DIR;
  193. UUIDFile = new File(dirStr + File.separator
  194. + "uuid.json");
  195. if (!UUIDFile.exists()) {
  196. File dir = new File(UUIDFile.getParent());
  197. dir.mkdirs();
  198. UUIDFile.createNewFile();
  199. }
  200. Gson gson = new Gson();
  201. FileUtils.writeFile(UUIDFile,
  202. gson.toJson(sysUserUUIDs).toString());
  203. } else {
  204. Toast.makeText(MainActivity.this, "sd卡错误", 1)
  205. .show();
  206. }
  207. long end = new Date().getTime();
  208. UUIDLoadCost = end - start;
  209. handler.sendEmptyMessage(LOAD_UUID_MSG);
  210. } catch (Exception e) {
  211. e.printStackTrace();
  212. }
  213. };
  214. }.start();
  215. }
  216. });
  217. btnStartLoadTestInt.setOnClickListener(new OnClickListener() {
  218. @Override
  219. public void onClick(View arg0) {
  220. pbInProgress.setVisibility(View.VISIBLE);
  221. intTestCnt = Integer.parseInt(etTestIntCount.getText()
  222. .toString());
  223. new Thread() {
  224. public void run() {
  225. try {
  226. long start = new Date().getTime();
  227. String sql = "select * from sysUserInt order by id limit "
  228. + intTestCnt + " offset 0 ";
  229. Cursor cr = db.mDb.query("sysUserInt",
  230. new String[] { "id", "uName" }, null, null,
  231. null, null, " id limit " + intTestCnt
  232. + " offset 0 ");
  233. sysUserInts = new ArrayList<SysUserInt>();
  234. while (cr.moveToNext()) {
  235. SysUserInt sysUserInt = new SysUserInt();
  236. sysUserInt.setId(cr.getInt(0));
  237. sysUserInt.setuName(cr.getString(1));
  238. sysUserInts.add(sysUserInt);
  239. }
  240. if (Environment.getExternalStorageState().equals(
  241. Environment.MEDIA_MOUNTED)) {
  242. String dirStr = Environment
  243. .getExternalStorageDirectory()
  244. .getPath()
  245. + File.separator + APP_DIR;
  246. intFile = new File(dirStr + File.separator
  247. + "int.json");
  248. if (!intFile.exists()) {
  249. File dir = new File(intFile.getParent());
  250. dir.mkdirs();
  251. intFile.createNewFile();
  252. }
  253. Gson gson = new Gson();
  254. FileUtils.writeFile(intFile,
  255. gson.toJson(sysUserInts).toString());
  256. } else {
  257. Toast.makeText(MainActivity.this, "sd卡错误", 1)
  258. .show();
  259. }
  260. long end = new Date().getTime();
  261. intLoadCost = end - start;
  262. handler.sendEmptyMessage(LOAD_INT_MSG);
  263. } catch (Exception e) {
  264. e.printStackTrace();
  265. }
  266. };
  267. }.start();
  268. }
  269. });
  270. }
  271. long UUIDLoadCost;
  272. long intLoadCost;
  273. void testIntId() {
  274. }
  275. void testUUIDId() {
  276. }
  277. }

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:81
帖子:4969
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP