MySQL提高插入数据的效率(结合JDBC)
0 解決問題最佳途徑:直接找官方
先說明的是,有問題直接去找官方文檔,而不應該去百度搜索,您很容易體驗到,搜索引擎很難快速找到真正對您有價值的解決方案,而官方文檔是最快捷的途徑。
本篇也是基于官方文檔和自己的實踐得出的一些經驗,適合初學者,本人也是初學者。
測試的插入數據只有353條,但是您依然能夠體會到性能的提升。
1 【40s】使用云數據庫Mysql的體驗
下面是使用JDBC和INSERT INTO語句逐條插入信息。
/*** 將訂單信息存入表 Performance_First** @param SalesOrder 銷售提交批量訂單* @param id 當前登錄賬戶的id*/ private static void InsertSalesOrder(int id, String name, int[] SalesOrder) throws SQLException {Connection connection = null;PreparedStatement insertSalesOrder = null;String insertSalesOrderSQL = "insert into Performance_First " +"values (?,?,0,now(),?,0)";long startTime = 0;try {connection = DatabaseOperation.CreateDatabaseConnection();assert connection != null;insertSalesOrder = connection.prepareStatement(insertSalesOrderSQL);startTime = System.currentTimeMillis();// TODO 記錄時間// 插入訂單for (int TemporarySalesOrder : SalesOrder) {insertSalesOrder.setInt(1, id);insertSalesOrder.setString(2, name);insertSalesOrder.setInt(3, TemporarySalesOrder);insertSalesOrder.execute();// 應該加點插入成功的標記}} catch (Exception e) {e.printStackTrace();} finally {DatabaseOperation.CloseDatabase(connection, insertSalesOrder);}long endTime = System.currentTimeMillis();System.out.println("程序運行時間:" + (endTime - startTime) + "ms"); }測試數據是353條,居然需要40s,我的天,難以忍受!
于是使用bing搜索半天,也沒有找到什么結果,之后看見了官方文檔,很快找到完美的解決方案。
首先,進入Mysql中文文檔,找到第7章 優化(可惜沒有搜索功能……)。
我們找到INSERT語句的速度。
入一個記錄需要的時間由下列因素組成,其中的數字表示大約比例:
連接:(3)
發送查詢給服務器:(2)
分析查詢:(2)
插入記錄:(1x記錄大小)
插入索引:(1x索引)
關閉:(1)
這不考慮打開表的初始開銷,每個并發運行的查詢打開。
好了,現在明白了,使用云數據庫,連接和發送就占用了大部分時間,所以,使用本地數據庫試一試?
2 【2s】提高性能:使用本地數據庫
這部分依然使用INSERT INTO語句,速度果然提高了很多,比較不需要聯網發送數據了。
不過,我們還想再快一點,此時,你需要知道,你不知道你不知道的知識,如果官方文檔找不到蛛絲馬跡,又沒有搜索,那就只能先去搜索引擎搜一下,看看我們需要解決那個位置的問題。
不過,幸運的是,官方文檔還真有。
當從一個文本文件裝載一個表時,使用LOAD DATA INFILE。這通常比使用很多INSERT語句快20倍。參見LOAD DATA INFILE語法。
3 【20ms】進一步提高性能:使用LOAD DATA INFILE而不是INSERT INTO
我們獲取了LOAD DATA INFILE的語法原型,然后使用我們需要的部分就可以了。
3.1 使用什么選項
我們的需求是
根據語法原型,我們需要的語法格式是
LOAD DATA INFILE [file_name] INTO TABLE [table_name](column1,column2,……) SET column5=expr,column6=expr……JDBC是這樣的(關鍵代碼)
String sql = "LOAD DATA INFILE ? " +"INTO TABLE Performance_First(SalesOrder) " +"SET ID=?,Name=?,QueryStatus=0,SubmitTime=now(),CalculateStatus=0"; try (Connection connection = DatabaseOperation.CreateDatabaseConnection(); // 連接數據庫 ) {assert connection != null;startTime = System.currentTimeMillis();try (PreparedStatement p = connection.prepareStatement(sql);) {p.setString(1, filePath);p.setInt(2, id);p.setString(3, name);p.execute();} }3.2 文件路徑:客戶端與服務器
如果指定了LOCAL,則被認為與連接的客戶端有關:
· 如果指定了LOCAL,則文件會被客戶主機上的客戶端讀取,并被發送到服務器。文件會被給予一個完整的路徑名稱,以指定確切的位置。如果給定的是一個相對的路徑名稱,則此名稱會被理解為相對于啟動客戶端時所在的目錄。
- 如果LOCAL沒有被指定,則文件必須位于服務器主機上,并且被服務器直接讀取。
當在服務器主機上為文件定位時,服務器使用以下規則: - 如果給定了一個絕對的路徑名稱,則服務器使用此路徑名稱。
- 如果給定了帶有一個或多個引導組件的相對路徑名稱,則服務器會搜索相對于服務器數據目錄的文件。
- 如果給定了一個不帶引導組件的文件名稱,則服務器會在默認數據庫的數據庫目錄中尋找文件。
注意,這些規則意味著名為./myfile.txt的文件會從服務器數據目錄中被讀取,而名為myfile.txt的同樣的文件會從默認數據庫的數據庫目錄中讀取。例如,下面的LOAD DATA語句會從db1數據庫目錄中讀取文件data.txt,因為db1是當前數據庫。即使語句明確把文件載入到db2數據庫中的表里,也會從db1目錄中讀取。
注意,使用正斜杠指定Windows路徑名稱,而不是使用反斜杠。如果您使用反斜杠,您必須使用兩個。
出于安全原因,當讀取位于服務器中的文本文件時,文件必須位于數據庫目錄中,或者是全體可讀的。另外,要對服務器文件使用LOAD DATA INFILE,您必須擁有FILE權限。
我們選擇直接使用服務器本地的文件,而不是客戶端遠程上傳,因此不需要加LOCAL。
此外,數據庫的文件會有默認的DATA文件夾,如果使用./則會認為是此文件夾,使用JDBC導入文件夾的時候,需要
注意加上后綴,并且,不要使用中文。
3.3 注意
總結
以上是生活随笔為你收集整理的MySQL提高插入数据的效率(结合JDBC)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 不孕不育夫妇如何正确就诊
- 下一篇: QT使用SQLite数据库实现登录功能