Mari kita lihat adegan temu bual dahulu:
Mungkin sesetengah rakan tidak pernah menemui jadual dengan berpuluh juta data, dan mereka tidak tahu apa yang akan berlaku apabila menanyakan berpuluh juta data.
Hari ini saya akan membawa anda melalui operasi praktikal Kali ini berdasarkan versi MySQL 5.7.26 untuk ujian
Apa yang perlu dilakukan jika anda tidak mempunyai data. ?
Buat
Kod untuk mencipta 10 juta? Itu mustahil, ia terlalu perlahan, dan mungkin mengambil masa sehari penuh. Anda boleh menggunakan skrip pangkalan data untuk melaksanakan dengan lebih pantas.
CREATE TABLE `user_operation_log` ( `id` int(11) NOT NULL AUTO_INCREMENT, `user_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `ip` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `op_data` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `attr1` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `attr2` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `attr3` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `attr4` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `attr5` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `attr6` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `attr7` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `attr8` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `attr9` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `attr10` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `attr11` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `attr12` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
Menggunakan sisipan kelompok, kecekapan akan menjadi lebih cepat, dan setiap 1000 item akan dilakukan Jumlah data terlalu besar, yang juga akan membawa kepada kecekapan sisipan kelompok yang perlahan
DELIMITER ;; CREATE PROCEDURE batch_insert_log() BEGIN DECLARE i INT DEFAULT 1; DECLARE userId INT DEFAULT 10000000; set @execSql = 'INSERT INTO `test`.`user_operation_log`(`user_id`, `ip`, `op_data`, `attr1`, `attr2`, `attr3`, `attr4`, `attr5`, `attr6`, `attr7`, `attr8`, `attr9`, `attr10`, `attr11`, `attr12`) VALUES'; set @execData = ''; WHILE i<=10000000 DO set @attr = "'测试很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长的属性'"; set @execData = concat(@execData, "(", userId + i, ", '10.0.69.175', '用户登录操作'", ",", @attr, ",", @attr, ",", @attr, ",", @attr, ",", @attr, ",", @attr, ",", @attr, ",", @attr, ",", @attr, ",", @attr, ",", @attr, ",", @attr, ")"); if i % 1000 = 0 then set @stmtSql = concat(@execSql, @execData,";"); prepare stmt from @stmtSql; execute stmt; DEALLOCATE prepare stmt; commit; set @execData = ""; else set @execData = concat(@execData, ","); end if; SET i=i+1; END WHILE; END;; DELIMITER ;
田哥的电脑配置比较低:win10 标压渣渣i5 读写约500MB的SSD
由于配置低,本次测试只准备了3148000条数据,占用了磁盘5G(还没建索引的情况下),跑了38min,电脑配置好的同学,可以插入多点数据测试
SELECT count(1) FROM `user_operation_log`
返回结果:3148000
三次查询时间分别为:
MySQL 支持 LIMIT 语句来选取指定的条数数据, Oracle 可以使用 ROWNUM 来选取。
MySQL分页查询语法如下:
SELECT * FROM table LIMIT [offset,] rows | rows OFFSET offset
下面我们开始测试查询结果:
SELECT * FROM `user_operation_log` LIMIT 10000, 10
查询3次时间分别为:
这样看起来速度还行,不过是本地数据库,速度自然快点。
换个角度来测试
SELECT * FROM `user_operation_log` LIMIT 10000, 10 SELECT * FROM `user_operation_log` LIMIT 10000, 100 SELECT * FROM `user_operation_log` LIMIT 10000, 1000 SELECT * FROM `user_operation_log` LIMIT 10000, 10000 SELECT * FROM `user_operation_log` LIMIT 10000, 100000 SELECT * FROM `user_operation_log` LIMIT 10000, 1000000
查询时间如下:
Kuantiti | Kali pertama | Kali kedua | Kali ketiga | |||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
10 item | 5ms | |||||||||||||||||||||
50ms | 60ms | 55ms | ||||||||||||||||||||
61ms | 74ms | 60ms | ||||||||||||||||||||
10000 item | 164ms | 180ms | 217ms | |||||||||||||||||||
100000 item | 1609ms | 1ms174ms | 1ms174ms | |||||||||||||||||||
16219ms | 16889ms | 17081ms |
偏移量 | 第一次 | 第二次 | 第三次 | |||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
100 | 36ms | 40ms | 36ms | |||||||||||||||||||
1000 | 31ms | 38ms | 32ms | |||||||||||||||||||
10000 | 53ms | 48ms | 51ms | |||||||||||||||||||
100000 | 622ms | 576ms | 627ms | |||||||||||||||||||
1000000 | 4891ms | 6ms508ms |
Artikel ketiga (tanpa indeks) | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Artikel ketiga (dengan indeks) | 201ms | |||||||||||||
sql | 花费时间 |
---|---|
第一条 | 22ms |
第二条 | 21ms |
从结果可以看出这种方式非常快
注意:这里的 LIMIT 是限制了条数,没有采用偏移量
返回结果的数据量也会直接影响速度
SELECT * FROM `user_operation_log` LIMIT 1, 1000000 SELECT id FROM `user_operation_log` LIMIT 1, 1000000 SELECT id, user_id, ip, op_data, attr1, attr2, attr3, attr4, attr5, attr6, attr7, attr8, attr9, attr10, attr11, attr12 FROM `user_operation_log` LIMIT 1, 1000000
查询结果如下:
sql | 花费时间 |
---|---|
第一条 | 15676ms |
第二条 | 7298ms |
第三条 | 15960ms |
Dapat dilihat daripada keputusan bahawa dengan mengurangkan lajur yang tidak diperlukan, kecekapan pertanyaan juga boleh dipertingkatkan dengan ketara
Kelajuan pertanyaan pertama dan ketiga adalah hampir sama Pada masa ini, anda pasti akan mengeluh, jadi mengapa saya perlu tulis begitu banyak medan? , hanya * dan anda sudah selesai
Perhatikan bahawa pelayan MySQL dan klien saya berada pada mesin yang sama, jadi data pertanyaan adalah serupa boleh menguji klien dan MySQL secara berasingan
Dengan cara ini, saya ingin menambah mengapa SELECT * harus diharamkan. Sedap kan sebab ringkas dan tak masuk akal?
Dua perkara utama:
Akhir sekali, saya harap anda boleh mengamalkannya sendiri, dan anda pasti akan mendapat lebih banyak lagi!
Atas ialah kandungan terperinci Penemubual: Bagaimana dengan cepat menanyakan berpuluh juta data?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!