Rumah >Java >JavaSoalan temu bual >Penemuduga: Bagaimanakah anda menanyakan 10 juta data?
Baru-baru ini, saya telah melakukan temu bual olok-olok dan pengoptimuman semula untuk semua orang, dan saya mendapati ramai orang menjadi lemah pada lutut apabila melihat soalan seperti berpuluh juta data.
Mungkin sesetengah orang 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 latihan praktikal Kali ini berdasarkan MySQL 5.7.26 untuk ujian
Apa yang perlu dilakukan jika anda tiada data. ?
Anda tidak boleh menciptanya sendiri tanpa data?
Adakah sukar untuk mencipta data?
10 juta penciptaan kod?
Itu mustahil, ia terlalu perlahan, ia mungkin benar-benar membawa anda sehari suntuk untuk berlari. 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;e
hanya 3148000 keping data disediakan untuk ujian ini, menduduki cakera itu 5G (belum pengindeksan), dan ia berjalan selama 38 minit Pelajar dengan konfigurasi komputer yang baik boleh memasukkan berbilang titik data untuk ujian
SELECT count(1) FROM `user_operation_log`
Kembalikan keputusan: 3148000
.Tiga masa pertanyaan ialah:
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 | |||||||||||||||||||||||||||||||||||||||||||||||||||
164ms | ms180ms | 100000 item | |||||||||||||||||||||||||||||||||||||||||||||||||||
1741ms | 1764ms | 1000000 item | |||||||||||||||||||||||||||||||||||||||||||||||||||
16889ms | 17081ms |
从上面结果可以得出结束:数据量越大,花费时间越长 相同数据量,不同偏移量SELECT * FROM `user_operation_log` LIMIT 100, 100 SELECT * FROM `user_operation_log` LIMIT 1000, 100 SELECT * FROM `user_operation_log` LIMIT 10000, 100 SELECT * FROM `user_operation_log` LIMIT 100000, 100 SELECT * FROM `user_operation_log` LIMIT 1000000, 100
从上面结果可以得出结束:偏移量越大,花费时间越长 SELECT * FROM `user_operation_log` LIMIT 100, 100 SELECT id, attr FROM `user_operation_log` LIMIT 100, 100 如何优化既然我们经过上面一番的折腾,也得出了结论,针对上面两个问题:偏移大、数据量大,我们分别着手优化 优化偏移量大问题采用子查询方式我们可以先定位偏移位置的 id,然后再查询数据 SELECT * FROM `user_operation_log` LIMIT 1000000, 10 SELECT id FROM `user_operation_log` LIMIT 1000000, 1 SELECT * FROM `user_operation_log` WHERE id >= (SELECT id FROM `user_operation_log` LIMIT 1000000, 1) LIMIT 10 查询结果如下:
从上面结果得出结论:
缺点:只适用于id递增的情况 id非递增的情况可以使用以下写法,但这种缺点是分页查询只能放在子查询里面 注意:某些 mysql 版本不支持在 in 子句中使用 limit,所以采用了多个嵌套select SELECT * FROM `user_operation_log` WHERE id IN (SELECT t.id FROM (SELECT id FROM `user_operation_log` LIMIT 1000000, 10) AS t) 采用 id 限定方式这种方法要求更高些,id必须是连续递增,而且还得计算id的范围,然后使用 between,sql如下 SELECT * FROM `user_operation_log` WHERE id between 1000000 AND 1000100 LIMIT 100 SELECT * FROM `user_operation_log` WHERE id >= 1000000 LIMIT 100 查询结果如下:
从结果可以看出这种方式非常快 注意:这里的 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 查询结果如下:
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 dan klien MySQL saya berada pada mesin yang sama, jadi data pertanyaan serupa boleh menguji klien dan MySQL secara berasingan PILIH *. Sedap tak baunya?Dengan cara ini, saya ingin menambah di sini mengapa kita harus mengharamkan 主要两点:
SELECT * " Pangkalan data perlu menghuraikan lebih banyak objek, medan, kebenaran, atribut, dsb. Kandungan, apabila pernyataan SQL adalah kompleks dan terdapat banyak penghuraian keras, ia akan menyebabkan beban berat pada pangkalan data. |
Atas ialah kandungan terperinci Penemuduga: Bagaimanakah anda menanyakan 10 juta data?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!