sqlite_test.go 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932
  1. package sqlite_test
  2. import (
  3. "database/sql"
  4. "encoding/json"
  5. "fmt"
  6. "math/rand"
  7. "reflect"
  8. "runtime"
  9. "strconv"
  10. "strings"
  11. "testing"
  12. "time"
  13. "github.com/wecisecode/util/cast"
  14. )
  15. func TestSQLiteBasic(t *testing.T) {
  16. // sqlite 内存表结构中字段类型只有 int64 float64 string, string没有长度限制
  17. // create table 中指定的类型没有意义,不影响数据插入
  18. // 实际数据类型是 由 第一次插入的数据的类型 决定的
  19. // 查询时,后续数据会强制转换为该类型,转不过去会报错,如将非数字字符串转换为数值
  20. mdb, err := sql.Open("sqlite", ":memory:")
  21. if err != nil {
  22. println("err", fmt.Sprint(err))
  23. return
  24. }
  25. stmt, err := mdb.Prepare(`CREATE TABLE TEST(
  26. ID INT PRIMARY KEY NOT NULL,
  27. NAME TEXT NOT NULL,
  28. VALUE REAL NOT NULL,
  29. INTVALUE INT NOT NULL,
  30. DESC CHAR(1)
  31. )`)
  32. if err != nil {
  33. println("err", fmt.Sprint(err))
  34. return
  35. }
  36. rslt, err := stmt.Exec()
  37. if err != nil {
  38. println("err", fmt.Sprint(err))
  39. return
  40. }
  41. println("rslt", fmt.Sprint(rslt.LastInsertId()), fmt.Sprint(rslt.RowsAffected()))
  42. stmt, err = mdb.Prepare("insert into test(id,name,intvalue,value,desc) values(?,?,?,?,?)")
  43. if err != nil {
  44. println("err", fmt.Sprint(err))
  45. return
  46. }
  47. for i := 1; i < 10; i++ {
  48. id := string([]byte{})
  49. for n := 0; n < 16; n++ {
  50. id = id + string('a'+byte(n+i-1))
  51. }
  52. name := int64(30 + i)
  53. floatvalue := int64(12345)
  54. var intvalue interface{}
  55. intvalue = 1.2345 * float32(i)
  56. if i%3 == 0 {
  57. intvalue = "--12345--"
  58. } else if i%3 == 2 {
  59. intvalue = 123450 + i
  60. }
  61. desc := string("........................................................................................")
  62. rslt, err = stmt.Exec(id, name, intvalue, floatvalue, desc)
  63. if err != nil {
  64. println("err", fmt.Sprint(err))
  65. }
  66. println("rslt", fmt.Sprint(rslt.LastInsertId()), fmt.Sprint(rslt.RowsAffected()))
  67. }
  68. stmt, err = mdb.Prepare("select * from test")
  69. if err != nil {
  70. println("err", fmt.Sprint(err))
  71. return
  72. }
  73. rows, err := stmt.Query()
  74. if err != nil {
  75. println("err", fmt.Sprint(err))
  76. return
  77. }
  78. defer func() { _ = rows.Close() }()
  79. cols, err := rows.Columns()
  80. if err != nil {
  81. println("err", fmt.Sprint(err))
  82. return
  83. }
  84. colTypes, err := rows.ColumnTypes()
  85. if err != nil {
  86. println("err", fmt.Sprint(err))
  87. return
  88. }
  89. types := make([]reflect.Type, len(colTypes))
  90. for i, tp := range colTypes {
  91. st := tp.ScanType()
  92. if st == nil {
  93. continue
  94. }
  95. types[i] = st
  96. }
  97. for rows.Next() {
  98. values := make([]interface{}, len(cols))
  99. for i := range values {
  100. values[i] = reflect.New(types[i]).Interface()
  101. }
  102. if err = rows.Scan(values...); err != nil {
  103. println("err", fmt.Sprint(err))
  104. return
  105. }
  106. m := make(map[string]interface{})
  107. for i, v := range values {
  108. if v == nil {
  109. //values[i] = nil
  110. m[colTypes[i].Name()] = nil
  111. } else {
  112. n, ok := colTypes[i].Length()
  113. m[colTypes[i].Name()] = fmt.Sprint(types[i], "[", n, "]", ok, ":", reflect.ValueOf(v).Elem().Interface())
  114. }
  115. }
  116. bs, _ := json.MarshalIndent(m, "", " ")
  117. println("values", string(bs))
  118. }
  119. }
  120. // GOMAXPROCS 1
  121. // Fields count 104
  122. // Empty Fields count 100
  123. // VarFields data length 32
  124. // Data count 10000
  125. // sqlite create table use time 1.6279ms
  126. // sqlite create index use time 0s
  127. // generate maps 10000 use time 1.1913207s
  128. // sqlite insert with transaction 10000 use time 1.9912916s
  129. // sqlite insert with transaction 10000 use time 1.9434772s
  130. // sqlite insert immediately prepare 10000 use time 2.0023365s
  131. // sqlite insert immediately 10000 use time 6.1372897s
  132. // sqlite select query all use time 746.4µs
  133. // sqlite fetch data 40000 use time 9.9554222s
  134. // put id-data maps 10000 use time 17.2197ms
  135. // fetch maps data ids 10000 use time 6.8757ms
  136. // fetch maps data 10000 use time 1.0318ms
  137. //
  138. // GOMAXPROCS 4
  139. // Fields count 104
  140. // Empty Fields count 100
  141. // VarFields data length 32
  142. // Data count 10000
  143. // sqlite create table use time 2.6123ms
  144. // sqlite create index use time 0s
  145. // generate maps 10000 use time 932.7881ms
  146. // sqlite insert with transaction 10000 use time 1.9001722s
  147. // sqlite insert with transaction 10000 use time 1.887692s
  148. // sqlite insert immediately prepare 10000 use time 2.0469167s
  149. // sqlite insert immediately 10000 use time 3.6564142s
  150. // sqlite select query all use time 432.8µs
  151. // sqlite fetch data 40000 use time 8.4194779s
  152. // put id-data maps 10000 use time 15.1188ms
  153. // fetch maps data ids 10000 use time 5.1524ms
  154. // fetch maps data 10000 use time 167.9µs
  155. //
  156. // GOMAXPROCS 8
  157. // Fields count 104
  158. // Empty Fields count 100
  159. // VarFields data length 32
  160. // Data count 10000
  161. // sqlite create table use time 2.1335ms
  162. // sqlite create index use time 0s
  163. // generate maps 10000 use time 874.8548ms
  164. // sqlite insert with transaction 10000 use time 1.8495912s
  165. // sqlite insert with transaction 10000 use time 1.773086s
  166. // sqlite insert immediately prepare 10000 use time 1.9181581s
  167. // sqlite insert immediately 10000 use time 3.2221547s
  168. // sqlite select query all use time 235.7µs
  169. // sqlite fetch data 40000 use time 7.541716s
  170. // put id-data maps 10000 use time 14.8666ms
  171. // fetch maps data ids 10000 use time 5.7673ms
  172. // fetch maps data 10000 use time 81.5µs
  173. func TestSQLiteProfmance(t *testing.T) {
  174. runtime.GOMAXPROCS(4)
  175. println("GOMAXPROCS ", runtime.GOMAXPROCS(0))
  176. varfieldscount := 100
  177. println("Fields count ", varfieldscount+4)
  178. emptyfieldscount := 100
  179. println("Empty Fields count ", emptyfieldscount)
  180. vardatalength := 32
  181. println("VarFields data length ", vardatalength)
  182. datacount := 10000
  183. println("Data count ", datacount)
  184. st := time.Now()
  185. mdb, err := sql.Open("sqlite", ":memory:")
  186. // mdb, err := sql.Open("sqlite", "file::memory:?cache=shared")
  187. if err != nil {
  188. println("err", fmt.Sprint(err))
  189. }
  190. fields := "id,name,value,desc"
  191. askmarks := "?,?,?,?"
  192. for i := 1; i <= varfieldscount; i++ {
  193. fields += ",var" + strconv.Itoa(i)
  194. askmarks += ",?"
  195. }
  196. allfields := fields
  197. for i := varfieldscount + 1; i <= varfieldscount+emptyfieldscount; i++ {
  198. allfields += ",var" + strconv.Itoa(i)
  199. }
  200. stmt, err := mdb.Prepare("create table if not exists test(" + allfields + ")")
  201. if err != nil {
  202. println("err", fmt.Sprint(err))
  203. return
  204. }
  205. rslt, err := stmt.Exec()
  206. if err != nil {
  207. println("err", fmt.Sprint(err))
  208. return
  209. }
  210. if rslt == nil {
  211. println("sqlite init table return nil")
  212. } else {
  213. id, err := rslt.LastInsertId()
  214. if err != nil {
  215. println("err", fmt.Sprint(err))
  216. return
  217. }
  218. ra, err := rslt.RowsAffected()
  219. if err != nil {
  220. println("err", fmt.Sprint(err))
  221. return
  222. }
  223. if id != 0 || ra != 0 {
  224. println("sqlite init table return ", id, ra)
  225. }
  226. }
  227. println("sqlite create table use time ", time.Since(st).String())
  228. st = time.Now()
  229. stmt, err = mdb.Prepare("create index test_id_1 on test (id)")
  230. if err != nil {
  231. println("err", fmt.Sprint(err))
  232. return
  233. }
  234. rslt, err = stmt.Exec()
  235. if err != nil {
  236. println("err", fmt.Sprint(err))
  237. return
  238. }
  239. if rslt == nil {
  240. println("sqlite init table index return nil")
  241. } else {
  242. id, err := rslt.LastInsertId()
  243. if err != nil {
  244. println("err", fmt.Sprint(err))
  245. return
  246. }
  247. ra, err := rslt.RowsAffected()
  248. if err != nil {
  249. println("err", fmt.Sprint(err))
  250. return
  251. }
  252. if id != 0 || ra != 0 {
  253. println("sqlite init table index return ", id, ra)
  254. }
  255. }
  256. println("sqlite create index use time ", time.Since(st).String())
  257. st = time.Now()
  258. data := []map[string]interface{}{}
  259. for i := 1; i <= datacount; i++ {
  260. m := map[string]interface{}{}
  261. m["id"] = i
  262. m["name"] = fmt.Sprint("name", i)
  263. m["value"] = 1.23456789 * float64(i)
  264. m["desc"] = strings.Repeat(fmt.Sprint("desc", i, "."), 10)
  265. for vi := 1; vi <= varfieldscount; vi++ {
  266. bs := make([]byte, vardatalength+rand.Intn(10)-5)
  267. for bsi := 0; bsi < len(bs); bsi++ {
  268. bs[bsi] = byte(32 + rand.Intn(95))
  269. }
  270. m["var"+strconv.Itoa(vi)] = string(bs)
  271. }
  272. data = append(data, m)
  273. // if i%10000 == 0 {
  274. // println("generate maps ", i, " use time ", time.Since(st).String())
  275. // }
  276. }
  277. println("generate maps ", datacount, " use time ", time.Since(st).String())
  278. st = time.Now()
  279. {
  280. mdb.Exec("PRAGMA synchronous = OFF") // 这个跟写文件相关,内存模式没用
  281. mdb.Exec("begin")
  282. stmt, err = mdb.Prepare("insert into test(" + fields + ") values(" + askmarks + ")")
  283. if err != nil {
  284. println("err", fmt.Sprint(err))
  285. return
  286. }
  287. for _, d := range data {
  288. args := []interface{}{
  289. d["id"],
  290. d["name"],
  291. d["value"],
  292. d["desc"]}
  293. for vi := 1; vi <= varfieldscount; vi++ {
  294. args = append(args, d["var"+strconv.Itoa(vi)])
  295. }
  296. rslt, err = stmt.Exec(args...)
  297. if err != nil {
  298. println("err", fmt.Sprint(err))
  299. }
  300. // println("rslt", fmt.Sprint(rslt.LastInsertId()), fmt.Sprint(rslt.RowsAffected()))
  301. // if (i+1)%10000 == 0 {
  302. // println("sqlite insert ", (i + 1), " use time ", time.Since(st).String())
  303. // }
  304. }
  305. mdb.Exec("commit")
  306. mdb.Exec("PRAGMA synchronous = NORMAL") // 这个跟写文件相关,内存模式没用
  307. println("sqlite insert with transaction ", len(data), " use time ", time.Since(st).String())
  308. }
  309. st = time.Now()
  310. tx, err := mdb.Begin()
  311. if err != nil {
  312. println("err", fmt.Sprint(err))
  313. return
  314. }
  315. stmt, err = tx.Prepare("insert into test(" + fields + ") values(" + askmarks + ")")
  316. if err != nil {
  317. println("err", fmt.Sprint(err))
  318. return
  319. }
  320. for _, d := range data {
  321. args := []interface{}{
  322. d["id"],
  323. d["name"],
  324. d["value"],
  325. d["desc"]}
  326. for vi := 1; vi <= varfieldscount; vi++ {
  327. args = append(args, d["var"+strconv.Itoa(vi)])
  328. }
  329. rslt, err = stmt.Exec(args...)
  330. if err != nil {
  331. println("err", fmt.Sprint(err))
  332. }
  333. // println("rslt", fmt.Sprint(rslt.LastInsertId()), fmt.Sprint(rslt.RowsAffected()))
  334. // if (i+1)%10000 == 0 {
  335. // println("sqlite insert ", (i + 1), " use time ", time.Since(st).String())
  336. // }
  337. }
  338. tx.Commit()
  339. println("sqlite insert with transaction ", len(data), " use time ", time.Since(st).String())
  340. st = time.Now()
  341. stmt, err = mdb.Prepare("insert into test(" + fields + ") values(" + askmarks + ")")
  342. if err != nil {
  343. println("err", fmt.Sprint(err))
  344. return
  345. }
  346. for _, d := range data {
  347. args := []interface{}{
  348. d["id"],
  349. d["name"],
  350. d["value"],
  351. d["desc"]}
  352. for vi := 1; vi <= varfieldscount; vi++ {
  353. args = append(args, d["var"+strconv.Itoa(vi)])
  354. }
  355. rslt, err = stmt.Exec(args...)
  356. if err != nil {
  357. println("err", fmt.Sprint(err))
  358. }
  359. // println("rslt", fmt.Sprint(rslt.LastInsertId()), fmt.Sprint(rslt.RowsAffected()))
  360. // if (i+1)%10000 == 0 {
  361. // println("sqlite insert ", (i + 1), " use time ", time.Since(st).String())
  362. // }
  363. }
  364. println("sqlite insert immediately prepare ", len(data), " use time ", time.Since(st).String())
  365. st = time.Now()
  366. for _, d := range data {
  367. args := []interface{}{
  368. d["id"],
  369. d["name"],
  370. d["value"],
  371. d["desc"]}
  372. for vi := 1; vi <= varfieldscount; vi++ {
  373. args = append(args, d["var"+strconv.Itoa(vi)])
  374. }
  375. sql := "insert into test(" + fields + ") values("
  376. for i, arg := range args {
  377. if i > 0 {
  378. sql += ","
  379. }
  380. switch a := arg.(type) {
  381. case string:
  382. sql += "'" + strings.ReplaceAll(a, "'", "''") + "'"
  383. default:
  384. sql += fmt.Sprint(arg)
  385. }
  386. }
  387. sql += ")"
  388. rslt, err = mdb.Exec(sql)
  389. if err != nil {
  390. println("err", fmt.Sprint(err))
  391. }
  392. // println("rslt", fmt.Sprint(rslt.LastInsertId()), fmt.Sprint(rslt.RowsAffected()))
  393. // if (i+1)%10000 == 0 {
  394. // println("sqlite insert ", (i + 1), " use time ", time.Since(st).String())
  395. // }
  396. }
  397. println("sqlite insert immediately ", len(data), " use time ", time.Since(st).String())
  398. st = time.Now()
  399. stmt, err = mdb.Prepare("select * from test")
  400. if err != nil {
  401. println("err", fmt.Sprint(err))
  402. return
  403. }
  404. rows, err := stmt.Query()
  405. if err != nil {
  406. println("err", fmt.Sprint(err))
  407. return
  408. }
  409. println("sqlite select query all", " use time ", time.Since(st).String())
  410. defer func() { _ = rows.Close() }()
  411. cols, err := rows.Columns()
  412. if err != nil {
  413. println("err", fmt.Sprint(err))
  414. return
  415. }
  416. colTypes, err := rows.ColumnTypes()
  417. if err != nil {
  418. println("err", fmt.Sprint(err))
  419. return
  420. }
  421. types := make([]reflect.Type, len(colTypes))
  422. for i, tp := range colTypes {
  423. st := tp.ScanType()
  424. if st == nil {
  425. continue
  426. }
  427. types[i] = st
  428. }
  429. data = []map[string]interface{}{}
  430. for rows.Next() {
  431. values := make([]interface{}, len(cols))
  432. for i := range values {
  433. if types[i] == nil {
  434. values[i] = &[]byte{}
  435. } else {
  436. values[i] = reflect.New(types[i]).Interface()
  437. }
  438. }
  439. if err = rows.Scan(values...); err != nil {
  440. println("err", fmt.Sprint(err))
  441. return
  442. }
  443. m := make(map[string]interface{})
  444. for i, v := range values {
  445. if v == nil {
  446. //values[i] = nil
  447. m[colTypes[i].Name()] = nil
  448. } else {
  449. n, ok := colTypes[i].Length()
  450. m[colTypes[i].Name()] = fmt.Sprint(types[i], "[", n, "]", ok, ":", reflect.ValueOf(v).Elem().Interface())
  451. }
  452. }
  453. data = append(data, m)
  454. // if len(data)%10000 == 0 {
  455. // println("sqlite fetch data ", len(data), " use time ", time.Since(st).String())
  456. // }
  457. }
  458. println("sqlite fetch data ", len(data), " use time ", time.Since(st).String())
  459. st = time.Now()
  460. memdataset := map[string]map[string]interface{}{}
  461. for _, d := range data {
  462. id := cast.ToString(d["id"])
  463. memdataset[id] = d
  464. }
  465. println("put id-data maps ", len(memdataset), " use time ", time.Since(st).String())
  466. st = time.Now()
  467. ids := []string{}
  468. for id, d := range memdataset {
  469. if id == d["id"] {
  470. ids = append(ids, id)
  471. }
  472. }
  473. println("fetch maps data ids ", len(ids), " use time ", time.Since(st).String())
  474. st = time.Now()
  475. data = []map[string]interface{}{}
  476. for _, id := range ids {
  477. d := memdataset[id]
  478. data = append(data, d)
  479. }
  480. println("fetch maps data ", len(data), " use time ", time.Since(st).String())
  481. }
  482. func TestSQLiteJSON(t *testing.T) {
  483. // sqlite 内存表结构中字段类型只有 int64 float64 string, string没有长度限制
  484. // create table 中指定的类型没有意义,不影响数据插入
  485. // 实际数据类型是 由 第一次插入的数据的类型 决定的
  486. // 查询时,后续数据会强制转换为该类型,转不过去会报错,如将非数字字符串转换为数值
  487. mdb, err := sql.Open("sqlite", ":memory:")
  488. if err != nil {
  489. println("err", fmt.Sprint(err))
  490. return
  491. }
  492. stmt, err := mdb.Prepare(`CREATE TABLE TEST(
  493. ID INT PRIMARY KEY NOT NULL,
  494. NAME TEXT NOT NULL,
  495. VALUE REAL NOT NULL,
  496. INTVALUE INT NOT NULL,
  497. DESC CHAR(1)
  498. )`)
  499. if err != nil {
  500. println("err", fmt.Sprint(err))
  501. return
  502. }
  503. rslt, err := stmt.Exec()
  504. if err != nil {
  505. println("err", fmt.Sprint(err))
  506. return
  507. }
  508. println("rslt", fmt.Sprint(rslt.LastInsertId()), fmt.Sprint(rslt.RowsAffected()))
  509. stmt, err = mdb.Prepare("insert into test(id,name,intvalue,value,desc) values(?,?,?,?,?)")
  510. if err != nil {
  511. println("err", fmt.Sprint(err))
  512. return
  513. }
  514. for i := 1; i < 10; i++ {
  515. id := string([]byte{})
  516. for n := 0; n < 16; n++ {
  517. id = id + string('a'+byte(n+i-1))
  518. }
  519. name := int64(30 + i)
  520. floatvalue := 12345 + (i-1)*10000
  521. var intvalue interface{}
  522. intvalue = 1.2345 * float32(i)
  523. if i%3 == 1 {
  524. intvalue = "--12345--"
  525. } else if i%3 == 2 {
  526. intvalue = 123450 + i
  527. }
  528. bs, _ := json.MarshalIndent(map[string]interface{}{
  529. "value": floatvalue,
  530. }, "", " ")
  531. desc := string(bs)
  532. rslt, err = stmt.Exec(id, name, intvalue, floatvalue, desc)
  533. if err != nil {
  534. println("err", fmt.Sprint(err))
  535. }
  536. println("rslt", fmt.Sprint(rslt.LastInsertId()), fmt.Sprint(rslt.RowsAffected()))
  537. }
  538. {
  539. stmt, err = mdb.Prepare(`select * from test`)
  540. if err != nil {
  541. println("err", fmt.Sprint(err))
  542. return
  543. }
  544. rows, err := stmt.Query()
  545. if err != nil {
  546. println("err", fmt.Sprint(err))
  547. return
  548. }
  549. defer func() { _ = rows.Close() }()
  550. cols, err := rows.Columns()
  551. if err != nil {
  552. println("err", fmt.Sprint(err))
  553. return
  554. }
  555. colTypes, err := rows.ColumnTypes()
  556. if err != nil {
  557. println("err", fmt.Sprint(err))
  558. return
  559. }
  560. types := make([]reflect.Type, len(colTypes))
  561. for i, tp := range colTypes {
  562. st := tp.ScanType()
  563. if st == nil {
  564. continue
  565. }
  566. types[i] = st
  567. }
  568. for rows.Next() {
  569. values := make([]interface{}, len(cols))
  570. for i := range values {
  571. values[i] = reflect.New(types[i]).Interface()
  572. }
  573. if err = rows.Scan(values...); err != nil {
  574. println("err", fmt.Sprint(err))
  575. return
  576. }
  577. m := make(map[string]interface{})
  578. for i, v := range values {
  579. if v == nil {
  580. //values[i] = nil
  581. m[colTypes[i].Name()] = nil
  582. } else {
  583. n, ok := colTypes[i].Length()
  584. m[colTypes[i].Name()] = fmt.Sprint(types[i], "[", n, "]", ok, ":", reflect.ValueOf(v).Elem().Interface())
  585. }
  586. }
  587. bs, _ := json.MarshalIndent(m, "", " ")
  588. println("values", string(bs))
  589. }
  590. }
  591. stmt, err = mdb.Prepare(`select json_group_array(json_object(
  592. 'id', id,
  593. 'name', name,
  594. 'value', value)) as json
  595. from test
  596. where json_extract(desc, '$.value') > 20000 and json_extract(desc, '$.value') < 50000`)
  597. if err != nil {
  598. println("err", fmt.Sprint(err))
  599. return
  600. }
  601. rows, err := stmt.Query()
  602. if err != nil {
  603. println("err", fmt.Sprint(err))
  604. return
  605. }
  606. defer func() { _ = rows.Close() }()
  607. cols, err := rows.Columns()
  608. if err != nil {
  609. println("err", fmt.Sprint(err))
  610. return
  611. }
  612. colTypes, err := rows.ColumnTypes()
  613. if err != nil {
  614. println("err", fmt.Sprint(err))
  615. return
  616. }
  617. types := make([]reflect.Type, len(colTypes))
  618. for i, tp := range colTypes {
  619. st := tp.ScanType()
  620. if st == nil {
  621. continue
  622. }
  623. types[i] = st
  624. }
  625. for rows.Next() {
  626. values := make([]interface{}, len(cols))
  627. for i := range values {
  628. values[i] = reflect.New(types[i]).Interface()
  629. }
  630. if err = rows.Scan(values...); err != nil {
  631. println("err", fmt.Sprint(err))
  632. return
  633. }
  634. m := make(map[string]interface{})
  635. for i, v := range values {
  636. if v == nil {
  637. //values[i] = nil
  638. m[colTypes[i].Name()] = nil
  639. } else {
  640. n, ok := colTypes[i].Length()
  641. m[colTypes[i].Name()] = fmt.Sprint(types[i], "[", n, "]", ok, ":", reflect.ValueOf(v).Elem().Interface())
  642. }
  643. }
  644. bs, _ := json.MarshalIndent(m, "", " ")
  645. println("values", string(bs))
  646. }
  647. }
  648. func TestSQLiteProfmanceMultiTable(t *testing.T) {
  649. runtime.GOMAXPROCS(4)
  650. println("GOMAXPROCS ", runtime.GOMAXPROCS(0))
  651. tablecount := 10000
  652. println("Tables count ", tablecount)
  653. varfieldscount := 100
  654. println("VarFields count ", varfieldscount+4)
  655. emptyfieldscount := 100
  656. println("EmptyFields count ", emptyfieldscount)
  657. vardatalength := 32
  658. println("VarFields data length ", vardatalength)
  659. tableindexcount := 100
  660. println("TableIndex count ", tableindexcount)
  661. datacount := 10000
  662. println("Data count ", datacount)
  663. mdb, err := sql.Open("sqlite", ":memory:")
  664. // mdb, err := sql.Open("sqlite", "file::memory:?cache=shared")
  665. if err != nil {
  666. println("err", fmt.Sprint(err))
  667. }
  668. st := time.Now()
  669. for ti := 1; ti < tablecount; ti++ {
  670. tablename := fmt.Sprint("test", ti)
  671. fields := []string{"id", "name", "value", "desc"}
  672. varfields := strings.Join(fields, ",")
  673. askmarks := "?" + strings.Repeat(",?", len(fields)-1)
  674. for i := 1; i <= varfieldscount; i++ {
  675. fields = append(fields, "var"+strconv.Itoa(i))
  676. varfields += ",var" + strconv.Itoa(i)
  677. askmarks += ",?"
  678. }
  679. allfields := varfields
  680. for i := varfieldscount + 1; i <= varfieldscount+emptyfieldscount; i++ {
  681. fields = append(fields, "var"+strconv.Itoa(i))
  682. allfields += ",var" + strconv.Itoa(i)
  683. }
  684. st := time.Now()
  685. stmt, err := mdb.Prepare("create table if not exists " + tablename + "(" + allfields + ")")
  686. if err != nil {
  687. println("err", fmt.Sprint(err))
  688. return
  689. }
  690. rslt, err := stmt.Exec()
  691. if err != nil {
  692. println("err", fmt.Sprint(err))
  693. return
  694. }
  695. if rslt == nil {
  696. println("sqlite init table return nil")
  697. } else {
  698. id, err := rslt.LastInsertId()
  699. if err != nil {
  700. println("err", fmt.Sprint(err))
  701. return
  702. }
  703. ra, err := rslt.RowsAffected()
  704. if err != nil {
  705. println("err", fmt.Sprint(err))
  706. return
  707. }
  708. if id != 0 || ra != 0 {
  709. println("sqlite init table return ", id, ra)
  710. }
  711. }
  712. println("sqlite create table", tablename, "use time ", time.Since(st).String())
  713. }
  714. println("sqlite create table", tablecount, "done, use time ", time.Since(st).String())
  715. st = time.Now()
  716. for ti := 1; ti < tablecount; ti++ {
  717. tablename := fmt.Sprint("test", ti)
  718. fields := []string{"id", "name", "value", "desc"}
  719. varfields := strings.Join(fields, ",")
  720. askmarks := "?" + strings.Repeat(",?", len(fields)-1)
  721. for i := 1; i <= varfieldscount; i++ {
  722. fields = append(fields, "var"+strconv.Itoa(i))
  723. varfields += ",var" + strconv.Itoa(i)
  724. askmarks += ",?"
  725. }
  726. allfields := varfields
  727. for i := varfieldscount + 1; i <= varfieldscount+emptyfieldscount; i++ {
  728. fields = append(fields, "var"+strconv.Itoa(i))
  729. allfields += ",var" + strconv.Itoa(i)
  730. }
  731. st = time.Now()
  732. for i, field := range fields {
  733. if i > tableindexcount {
  734. break
  735. }
  736. stmt, err := mdb.Prepare("create index " + tablename + "_" + field + " on " + tablename + " (" + field + ")")
  737. if err != nil {
  738. println("err", fmt.Sprint(err))
  739. return
  740. }
  741. rslt, err := stmt.Exec()
  742. if err != nil {
  743. println("err", fmt.Sprint(err))
  744. return
  745. }
  746. if rslt == nil {
  747. println("sqlite init table index return nil")
  748. } else {
  749. id, err := rslt.LastInsertId()
  750. if err != nil {
  751. println("err", fmt.Sprint(err))
  752. return
  753. }
  754. ra, err := rslt.RowsAffected()
  755. if err != nil {
  756. println("err", fmt.Sprint(err))
  757. return
  758. }
  759. if id != 0 || ra != 0 {
  760. println("sqlite init table index return ", id, ra)
  761. }
  762. }
  763. }
  764. println("sqlite create index for table "+tablename+" use time ", time.Since(st).String())
  765. }
  766. println("sqlite create table index", tablecount, "done, use time ", time.Since(st).String())
  767. st = time.Now()
  768. data := []map[string]interface{}{}
  769. {
  770. st = time.Now()
  771. for i := 1; i <= datacount; i++ {
  772. m := map[string]interface{}{}
  773. m["id"] = i
  774. m["name"] = fmt.Sprint("name", i)
  775. m["value"] = 1.23456789 * float64(i)
  776. m["desc"] = strings.Repeat(fmt.Sprint("desc", i, "."), 10)
  777. for vi := 1; vi <= varfieldscount; vi++ {
  778. bs := make([]byte, vardatalength+rand.Intn(10)-5)
  779. for bsi := 0; bsi < len(bs); bsi++ {
  780. bs[bsi] = byte(32 + rand.Intn(95))
  781. }
  782. m["var"+strconv.Itoa(vi)] = string(bs)
  783. }
  784. data = append(data, m)
  785. if i%1000 == 0 {
  786. println("generate maps ", i, " use time ", time.Since(st).String())
  787. }
  788. }
  789. println("generate maps ", datacount, " use time ", time.Since(st).String())
  790. st = time.Now()
  791. memdataset := map[string]map[string]interface{}{}
  792. for _, d := range data {
  793. id := cast.ToString(d["id"])
  794. memdataset[id] = d
  795. }
  796. println("put id-data maps ", len(memdataset), " use time ", time.Since(st).String())
  797. st = time.Now()
  798. ids := []string{}
  799. for id, d := range memdataset {
  800. if id == cast.ToString(d["id"]) {
  801. ids = append(ids, id)
  802. }
  803. }
  804. println("fetch maps data ids ", len(ids), " use time ", time.Since(st).String())
  805. st = time.Now()
  806. data = []map[string]interface{}{}
  807. for _, id := range ids {
  808. d := memdataset[id]
  809. data = append(data, d)
  810. }
  811. println("fetch maps data ", len(data), " use time ", time.Since(st).String())
  812. }
  813. for ti := 1; ti < tablecount; ti++ {
  814. tablename := fmt.Sprint("test", ti)
  815. fields := []string{"id", "name", "value", "desc"}
  816. varfields := strings.Join(fields, ",")
  817. askmarks := "?" + strings.Repeat(",?", len(fields)-1)
  818. for i := 1; i <= varfieldscount; i++ {
  819. fields = append(fields, "var"+strconv.Itoa(i))
  820. varfields += ",var" + strconv.Itoa(i)
  821. askmarks += ",?"
  822. }
  823. allfields := varfields
  824. for i := varfieldscount + 1; i <= varfieldscount+emptyfieldscount; i++ {
  825. fields = append(fields, "var"+strconv.Itoa(i))
  826. allfields += ",var" + strconv.Itoa(i)
  827. }
  828. { // insert
  829. st = time.Now()
  830. stmt, err := mdb.Prepare("insert into " + tablename + "(" + varfields + ") values(" + askmarks + ")")
  831. if err != nil {
  832. println("err", fmt.Sprint(err))
  833. return
  834. }
  835. i := 0
  836. for _, d := range data {
  837. i = i + 1
  838. args := []interface{}{
  839. d["id"],
  840. d["name"],
  841. d["value"],
  842. d["desc"]}
  843. for vi := 1; vi <= varfieldscount; vi++ {
  844. args = append(args, d["var"+strconv.Itoa(vi)])
  845. }
  846. _, err := stmt.Exec(args...)
  847. if err != nil {
  848. println("err", fmt.Sprint(err))
  849. }
  850. // println("rslt", fmt.Sprint(rslt.LastInsertId()), fmt.Sprint(rslt.RowsAffected()))
  851. if i%1000 == 0 {
  852. println("sqlite insert ", i, " use time ", time.Since(st).String())
  853. }
  854. }
  855. println("sqlite insert ", tablename, len(data), " use time ", time.Since(st).String())
  856. }
  857. { // select
  858. st = time.Now()
  859. stmt, err := mdb.Prepare("select " + varfields + " from " + tablename)
  860. if err != nil {
  861. println("err", fmt.Sprint(err))
  862. return
  863. }
  864. rows, err := stmt.Query()
  865. if err != nil {
  866. println("err", fmt.Sprint(err))
  867. return
  868. }
  869. println("sqlite select query all", " use time ", time.Since(st).String())
  870. defer func() { _ = rows.Close() }()
  871. cols, err := rows.Columns()
  872. if err != nil {
  873. println("err", fmt.Sprint(err))
  874. return
  875. }
  876. colTypes, err := rows.ColumnTypes()
  877. if err != nil {
  878. println("err", fmt.Sprint(err))
  879. return
  880. }
  881. types := make([]reflect.Type, len(colTypes))
  882. for i, tp := range colTypes {
  883. st := tp.ScanType()
  884. if st == nil {
  885. continue
  886. }
  887. types[i] = st
  888. }
  889. data := []map[string]interface{}{}
  890. for rows.Next() {
  891. values := make([]interface{}, len(cols))
  892. for i := range values {
  893. if types[i] == nil {
  894. values[i] = &[]byte{}
  895. } else {
  896. values[i] = reflect.New(types[i]).Interface()
  897. }
  898. }
  899. if err = rows.Scan(values...); err != nil {
  900. println("err", fmt.Sprint(err))
  901. return
  902. }
  903. m := make(map[string]interface{})
  904. for i, v := range values {
  905. if v == nil {
  906. //values[i] = nil
  907. m[colTypes[i].Name()] = nil
  908. } else {
  909. n, ok := colTypes[i].Length()
  910. m[colTypes[i].Name()] = fmt.Sprint(types[i], "[", n, "]", ok, ":", reflect.ValueOf(v).Elem().Interface())
  911. }
  912. }
  913. data = append(data, m)
  914. // if len(data)%10000 == 0 {
  915. // println("sqlite fetch data ", len(data), " use time ", time.Since(st).String())
  916. // }
  917. }
  918. println("sqlite fetch data ", len(data), " use time ", time.Since(st).String())
  919. }
  920. }
  921. }