整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          在 Node.js 中使用 MySQL &a

          在 Node.js 中使用 MySQL & MySQL JavaScript 客戶端

          oSQL 數據庫最近一段時間都是很受追捧的,也許已經是 Node.js 應用程序的首選后端了。不過,你不應該只是根據潮流來選擇拿什么技術構建下一個項目,使用什么數據庫類型要取決于項目的特定需求。如果你的項目涉及到動態表的創建,實時的插入等等,那么 NoSQL 就是不錯的技術路線,而另一方面,如果項目中要處理復雜的查詢和事務,那么 SQL 數據庫就更加合適了。

          在本教程中,我們會向你介紹如何使用 MySQL 模塊 - 這是一個用 JavaScript 編寫的運行在 Node.js 之上的 MySQL 驅動程序。我會向你解釋如何使用該模塊連接到 MySQL 數據庫,執行常規的 CRUD 操作,之后就是對存儲的過程進行檢查,以及對用戶的輸入進行轉義這些技術。

          這個頗受歡迎的教程在 2017 年 11 月 07 日進行了更新。其中的修改包括將語法更新到了 ES6,解決了node-mysql 模塊被重新命名的問題,增加了更多對初學者友好的文字說明,并在 ORM 上新增加了一個部分。

          快速入門:如何在Node 中使用MySQL

          也許你來這是就是為了找到一個快速的法門。如果你是想用盡可能少的時間在 Node 中啟動并運行 MySQL,我們能滿足你的需求!

          以下5個簡單步驟告訴你如何在 Node 中使用 MySQL:

          1. 創建一個新項目:mkdir mysql-test && cd mysql-test

          2. 創建一個 package.json 文件:npm init -y

          3. 安裝mysql模塊: npm install mysql –save

          4. 創建一個app.js文件并將下面的代碼段復制進去。

          5. 運行該文件: node app.js。會看到一條 “Connected!”(已連接上了)消息。

          安裝 mysql 模塊

          現在讓我們細化到第一步。首先,我們使用命令行創建一個新目錄進進入這個目錄。然后我們使用 npm init -y 命令創建 package.json 文件。-y 參數表示 npm 會使用默認值而不會問你各種問題。

          這一步假設你已經在系統上安裝了 Node 和 npm。如果還沒安裝,請閱讀 SitePoint 上的這篇文章,它會指導你:使用 nvm 安裝 Node.js 的多個版本。

          然后,我們從 npm 安裝 mysql 模塊并將其保存為項目的依賴項。項目的 dependencies (相對于 dev-dependencies) 是運行程序所需要的包。你可以閱讀了解兩者的區別。

          如果你深入學習使用 npm,可以閱讀這個指南,或者在我們的論壇上提問。

          入門

          在我們連接到數據庫之前,有一件重要的事情就是要在你的機器上安裝和配置 MySQL。如果這件事情還沒做完,那就看看軟件主頁上的安裝說明自己去裝一個吧。

          接下來我們需要做的就是創建一個數據庫和一個數據庫表。你可以使用一個圖形用戶界面來做到這一點,比如說 phpMyAdmin,或者就使用命令行。 對于我們這篇文章,使用的是一個名為 sitepoint 的數據庫和一個名為 employees 的表。如果你希望跟著一起操作的話,這里有一個數據庫的轉儲文件,方便你可以快速地啟動并運行起來:

          連接到數據庫

          現在,我們在 mysql-test 目錄下創建一個名為 app.js 的文件,來看看如何從 Node.js 連接到 MySQL。

          現在打開一個終端并輸入 node app.js。在連接成功建立之后,你應該能夠在控制臺中看到“Connection established”(連接已經建立好了)這條消息了。 如果出現了什么問題(例如輸入了錯誤的密碼),程序就會觸發一個回調,該事件會傳遞出一個 JavaScript Error 對象(err)的實例。 你可以嘗試將其打印到控制臺以查看其中包含的有用信息以調試程序。

          使用 Grunt 來監視文件的更改

          每當我們對代碼進行更改時,手動運行 node app.js 命令會變得有點乏味,所以讓我們來把這個操作自動化吧。 這一節并不需要跟本教程的其余部分并沒有依賴關系,不過如果照著做的話肯定會為你節省一些麻煩事兒。

          我們首先得安裝幾個包:

          Grunt 是有名的 JavaScript 任務執行程序,每當監聽到有文件發生修改時,grunt-contrib-watch 都會運行已經預定義好的任務,并且會使用 grunt-execute 來運行 node app.js 命令。

          安裝完成之后,在項目根中創建一個名為Gruntfile.js的文件,然后在里面添加上如下代碼。

          現在運行 grunt watch 然后修改一下 app.js 文件。Grunt 就應該會檢測到我們修改了文件并重新運行 node app.js 命令。

          執行查詢

          讀取

          現在你知道如何在 Node.js 中建立 MySQL 連接了,再來看看如何執行 SQL 查詢。我們從這里開始:建立使用 createConnection 命令連接到名為 sitepoint 的數據庫。

          連接建立后我們要使用連接變量來對數據庫中的 employees 表進行查詢。

          現在運行 app.js (通過 grunt-watch 或者在終端輸入 node app.js),你可以看到終端輸出從數據庫返回的數據。

          從 MySQL 數據庫返回的數據可以通過遍歷 rows 對象來進行解析。

          創建

          你可以在數據庫中執行 insert 查詢,像這樣:

          請注意到我們是如何通過回調參數來獲得剛插入那條記錄的 ID 的。

          更新

          類似地,在執行 update 查詢的時候,通過 result.affectedRows 可得到受影響的行數:

          刪除

          delete 查詢的操作也差不多:

          高級用法

          我希望有辦法通過 mysql 模塊來處理存儲過程,以及轉義用戶輸入。

          存儲過程

          簡單的說,存儲過程是存儲在數據庫中,可以由數據庫引擎和連接上數據的程序語言調用的程序(例如,SQL 程序)。如果你需要復習,請看看這篇不錯的文章。

          先來為我們的 sitepoint 數據庫創建一個存儲過程,它用于獲取所有員工的詳情。我們把它命名為 sp_getall。為了做這件事,你需要某種數據庫接操作界面。我使用 phpMyAdmin。在 sitepoint 數據庫中運行下面的查詢:

          它會將程序保存在 information_schema 數據庫的 ROUTINGS 表中。

          下一步,建立連接并使用連接對象調用存儲過程,像這樣:

          保存修改并運行。運行的時候你可以看到從數據庫返回的數據。

          這些數據包括一些附加信息,比如影響的行數,insertId 等。你需要對返回數據的第 0 個元素進行遍歷以獲取員工詳情信息。

          現在考慮一個需要輸入參數的存儲過程。

          我們可以在調用存儲過程的時候傳入參數:

          多數時候,如果我們想在數據庫中插入一條記錄,需要將插入記錄的 ID 作為輸出參數返回出來。考慮接下來用于插入數據的存儲過程,它有一個輸出參數:

          為了調用含有輸出參數的存儲過程,我們需要在創建連接時調用多個程序。因此,修改連接,設置執行多個語句為 true。

          然后在調用存儲過程的時候,設置并傳入一個輸出參數。

          在上面的代碼中,我們設置了輸出參數 @employee_id 并在調用存儲過程的時候將其傳入。一旦調用完成,我們需要使用 select 查詢輸出參數來獲取返回的 ID。

          運行 app.js。如果執行成功你可以看到 select 查詢的輸出參數和各種其它信息。通過 rows[2] 可獲得輸出參數的值。

          轉義用戶輸入

          為了避免 SQL 注入攻擊,你應該總是轉義來自用戶的任何數據,然后再把它用于 SQL 查詢。來演示一下為什么:

          這看起來并沒有什么問題,它會返回正確的結果:

          不過,如果我們將 userLandVariable 改為:

          居然訪問了整個數據集。如果我們再改為這樣:

          這下麻煩大了!

          好消息是有辦法處理這類問題。你只需要使用 mysql.escape 方法:

          或者使用問號占位符,就像我們在文章一開始提到的那個示例一樣:

          為什么不簡單地使用 ORM?

          你可能注意到了,評論中有人建議使用 ORM。在詳述這個方法的優缺點之前,我先看看 ORM 是什么。下面是來自 Stack Overflow 的回答。

          對象關系映射(Object-Relational Mapping, ORM) 是一種允許人們使用面向對象范型來查詢和操作數據庫數據的技術。在談到 ORM 的時候,多數人是指實現了 ORM 技術的某個庫,所以會使用 “an ORM” 這樣的短語。

          因此,這種方法基本上意味著你會使用 ORM 領域相關的語言來編寫數據庫邏輯,而不是我們一直在討論的普通方法。下面以 Sequelize 為例:

          對比:

          使用 ORM 對你是否有意義,取決于很多與你工作相關的因素,比如你在做什么以及為誰做。一方面,ORM 的形式使開發更為高效,從某種程序上來說,它抽象了大部分的 SQL 因而不需要團隊中的每個人都去了解如何編寫高效的數據庫查詢。它也很容易遷移到不同的數據庫軟件,因為你是在抽象層次上進行開發。

          然而,從另一方面來說,由于不理解 ORM 是如何做的,所以可能會編寫出一些混亂和低效的 SQL。性能也會是一個大問題,畢竟優化不通過 ORM 的查詢要容易得多。

          到底采用哪一種方法,決定權在你,但是如果正在做這個決定,請看看這個 Stack Overflow 的帖子:為什么應該使用 ORM?,以及 SitePoint 上的:你可能不知道的 3 個 JavaScript ORM。

          小結

          本教程中只涉及到了 MySQL 客戶端的皮毛。我推薦你去閱讀官方文檔以了解更詳細的信息。當然也有別的選擇,比如 node-mysql2 和 node-mysql-libmysqlclient。

          你是否已經在 Node.js 中用過這些庫來連接到 MySQL?我很想聽人說說這些庫。請在下面的評論中告訴我們你的想法、建議以及更正意見!


          文章來源:開源中國

          【燈塔大數據】微信公眾號介紹:中國電信北京研究院通過整合電信自有數據、互聯網數據和線下數據,創建了業內領先的“燈塔”大數據行業應用平臺,致力于與行業合作伙伴共同打造大數據行業應用生態圈。目前我們面向市場研究、廣告、汽車、金融、人力資源等諸多行業領域,提供零售研究、消費者研究、店鋪選址、精準營銷、泛義征信等服務,助力企業在大數據時代楊帆遠航。

          微信公眾號【燈塔大數據】關鍵字信息:

          【人工智能】獲取人工智能時代的發展思考 ppt

          【半月刊】下載大數據瞭望半月刊

          【網絡安全】獲取國民網絡安全報告全文

          【23個理由】下載《大數據讓你興奮的23個理由》電子書

          【思維導圖】下載12種工具的獲取方式

          【 燈塔 】 查看更多關鍵字回復

          嘮嗑一下。都在說去O或者開源,但是對于數據庫選型來說,很多人卻存在著誤區。例如,去O,狹義上講,是去Oracle數據庫。但是從廣義上來說,是去Oracle公司產品或者具有漂亮國壟斷地位和需要商業授權的數據庫產品。

          去O,目前國內有一個現象,就是很多公司或個人聽到去O,第一反應是改用Mysql,實際上Mysql也是Oracle公司的。而且Mysql雖然是開源的,但是需要遵循GPL開源協議,這個協議里面(大概意思)含有這么兩點就可以窺見一斑:

          1、如果用Mysql源碼進行二次修改,修改后的產品也必須開源,例如目前國產分布式數據庫TiDB就遵循該協議進行開源;

          2、如果要對Mysql二次封裝或者修改后進行實現商業版本,就必須取得甲骨文公司授權。以上這兩條,就足以讓Mysql這款開源數據庫并不具備“開源優勢”,將來該被制裁還是會被制裁。

          目前去O,還有一款備選開源數據庫是PostgreSQL,它是基于BSD開源協議的,該開源協議是四大開源協議里面最“開放”和自由的,不會受到商業版權化影響,并且組織或個人也可以通過它的源碼進行二次封裝或者進行發行商業版,例如華為的OpenGuass是基于該開源版本進行二次開發的,并且基于PostgreSQL或者基于OpenGuass進行二次封裝成商業版本的數據庫(國產、非國產等)也比比皆是。


          以上只是吐個槽,本篇文章主要是想通過.NET6+EF CORE + 三大數據庫,進行一個在同等環境下的簡單的讀寫性能測試。


          【備注】由于各種原因,接下來的測試結果可能會不準確,以下僅供學習或參考使用。


          數據庫運行環境:Cent OS 7.5


          PostgreSQL版本:14

          MySQL數據庫版本:8.0

          Oracle數據庫:12C 64位


          客戶端環境:WIN 10 專業版

          運行時環境:.NET 6

          ORM:EF CORE

          開發語言:C#



          CentOS環境安裝PostgreSQL

          遠程服務器上已有授權的Oracle環境和Mysql環境,所以具體安裝細節不再進行描述,如果感興趣的小伙伴也可以自行百度一下Oracle和Mysql的安裝教程,應該非常多。由于服務器上暫時還沒有PostgreSQL環境,我暫且也把安裝PostgreSQL的安裝步驟也順手記錄下。


          PostgreSQL安裝:

          下載地址:

          https://www.postgresql.org/download/linux/redhat/

          選擇版本以后,會有對應提示的安裝方式命令,就不發出來了,可自行參考。


          以下是安裝以后的一些配置。

          安裝完畢,并且啟動pgsql服務以后,此處我先創建一個測試用的數據庫:testdb


          使用命令:su - postgres 可以進行默認的登錄,默認無密碼。

          登陸以后使用命令:psql 可以進入到可執行SQL的命令的頁面,以postgres=# 開頭。其他命令和有關創建用戶的SQL語句如圖所示。


          修改配置文件: /var/lib/pgsql/14/data/postgresql.conf

          將注釋的listen_addresses打開,設置值為 ‘*’

          路徑上的14代表版本,如果是13版本就是13,以此類推,下同。

          修改/var/lib/pgsql/14/data/pg_hba.conf配置文件,對IPV4訪問新增一行配置如下:

          然后要重啟pgsql服務,以用于生效。


          由于pgsql默認的端口是5432,為了可以跨遠程訪問,此處把遠程服務器上的端口開放出來。命令:firewall-cmd --zone=public --add-port=5432/tcp --permanent

          然后重載防火墻,命令:firewall-cmd --reload

          測試數據庫有關表結構。以下表均沒有設置索引,僅單表測試,結果僅供參考。

          Mysql表結構:

          PostgreSQL表結構:


          Oracle表結構:



          .NET 6開發測試代碼

          先創建一個minimal api項目,以及一個服務類庫項目。類庫引用需要操作Oracle數據庫、MySQL數據庫以及Postgresql數據庫有關的組件。



          對服務類設置為啟動項,然后新增三個文件夾(MyModel,OraModel和PgModel),用于分別存放三個數據庫的實體類。然后在程序包管理控制臺上,通過命令:

          Scaffold-DbContext “mysql連接字符串" Pomelo.EntityFrameworkCore.MySql -OutputDir MyModel -Force

          自動生成指定的mysql數據庫實體類。其中,MyModel是需要生成的目標目錄文件夾。


          通過命令:

          Scaffold-DbContext "Oracle連接字符串" Oracle.EntityFrameworkCore -OutputDir OraModel -Force

          自動生成Oracle數據庫實體類。


          通過命令:

          Scaffold-DbContext "pgsql連接字符串" Npgsql.EntityFrameworkCore.PostgreSQL -OutputDir PgModel -Force

          自動生成PostgreSQL數據庫實體類。



          新建一個測試服務類DatabaseTestService,提供簡單插入和更新功能:


          在minimai api項目里,新增兩個簡單的測試API用于測試。為了簡單,就直接實例化一下進行訪問,然后返回執行結果。


          以上方法可能執行適合會導致耗時而失敗,為了直觀一點,改成控制臺里面輸出。


          實現里面也做點調整。


          測試插入和更新

          運行程序以后,對三個數據庫分別插入數據并計時。

          先看Oracle物理表情況。

          插入總共數據條數:

          部分數據結果集:


          然后是mysql物理表數據。

          插入數據總數:

          部分數據結果集:


          最后是PostgreSQL。插入總條數:

          部分數據結果集:


          以下是通過EF CORE進行插入的結果:


          接下來進行一輪更新操作,為了防止數據量太大,所以只進行批量更新10000條數據。結果如下:


          看下數據更新結果是不是正常。

          Oracle數據:


          MySQL數據:


          PGSQL數據:


          數據庫數據清空,屏蔽掉C#代碼一些實體賦值時間,重新執行兩次僅統計批量插入數據庫部分的執行的時間進行重新測試,僅測試批量插入耗時結果。

          第一回測試結果:

          接下來不刪除數據,重新執行一輪。


          Oracle估計哪兒有問題,數據讓人很尷尬啊。接下來只比較MySQL和PgSQL

          來一波批量插入:


          再來一波三次的批量更新:


          有關代碼(最后測試使用)

           public class DatabaseTestService
              {
                  public String TestInsert()
                  {
                      StringBuilder sb=new StringBuilder();
                     Console.WriteLine("*************************開始插入測試************************");
                      for(int i=1; i < 5; i++)
                      {
                    //      Console.WriteLine(TestOracleInsert(i));
                          Console.WriteLine(TestMysqlInsert(i));
                          Console.WriteLine(TestPostgreSQLInsert(i));
                      }
                      return sb.ToString();
                  }
                  public String TestUpdate()
                  {
                      StringBuilder sb=new StringBuilder();
                      Console.WriteLine("*************************開始更新測試************************");
                      //       Console.WriteLine(TestOracleUpdate());
                      for (int i=0;i<3;i++) {
                          Console.WriteLine(TestMysqlUpdate(i));
                          Console.WriteLine(TestPostgreSQLUpdate(i));
                      }
                      return sb.ToString();
                  }
                  private String TestOracleInsert(int loop)
                  {
                      StringBuilder sb=new();
                      Stopwatch stopwatch=new();
                      List<OraModel.TestTable> tables=new();
          
                      for (int i=1; i <=50000; i++)
                      {
                          OraModel.TestTable table=new();
                          table.Id=Guid.NewGuid().ToString("N");
                          table.Message=$"第{loop}輪測試數據{i}";
                          table.CurrentTime=DateTime.Now;
                          table.Code=(loop * 5000) + i;
                          tables.Add(table);
                      }
                      using (var context=new OraModel.ModelContext())
                      {
                          try {
          
                              stopwatch.Start();
                              context.Database.BeginTransaction();
                              context.TestTables.AddRange(tables);
                              context.SaveChanges();
                              context.Database.CommitTransaction();
                              stopwatch.Stop();
                              sb.Append($"第{loop}輪插入50000條到【Oracle】數據庫【成功】:耗時{stopwatch.ElapsedMilliseconds} ms...");
          
                          }
                          catch(Exception ex)
                          {
                              context.Database.RollbackTransaction();
                              stopwatch.Stop();
                              sb.Append($"第{loop}輪插入50000條到【Oracle】數據庫【失敗】:耗時{stopwatch.ElapsedMilliseconds} ms...");
                          }
                          finally
                          {
                          }
                      }
          
                      return sb.ToString();
                  }
                  private String TestMysqlInsert(int loop)
                  {
                      StringBuilder sb=new();
                      Stopwatch stopwatch=new();
                      List<MyModel.TestTable> tables=new();
                      for (int i=1; i <=100000; i++)
                      {
                          MyModel.TestTable table=new();
                          table.Id=Guid.NewGuid().ToString("N");
                          table.Message=$"第{loop}輪測試數據{i}";
                          table.CurrentTime=DateTime.Now;
                          table.Code=i;
                          tables.Add(table);
                      }
                      using (var context=new MyModel.testdbContext())
                      {
                          try
                          {
                              stopwatch.Start();
                              context.Database.BeginTransaction();
                              context.TestTables.AddRange(tables);
                              context.SaveChanges();
                              context.Database.CommitTransaction();
                              stopwatch.Stop();
                              sb.Append($"第{loop}輪插入100000條到【MySQL】數據庫【成功】:耗時{stopwatch.ElapsedMilliseconds} ms...");
          
                          }
                          catch (Exception ex)
                          {
                              context.Database.RollbackTransaction();
                              stopwatch.Stop();
                              sb.Append($"第{loop}輪插入100000條到【MySQL】數據庫【失敗】:耗時{stopwatch.ElapsedMilliseconds} ms...");
                          }
                          finally
                          {
                          }
                      }
          
                      return sb.ToString();
                  }
                  private String TestPostgreSQLInsert(int loop)
                  {
                      StringBuilder sb=new();
                      Stopwatch stopwatch=new();
                      List<PgModel.TestTable> tables=new();
          
                      for (int i=1; i <=100000; i++)
                      {
                          PgModel.TestTable table=new();
                          table.Id=Guid.NewGuid().ToString("N");
                          table.Message=$"第{loop}輪測試數據{i}";
                          table.CurrentTime=DateTime.Now;
                          table.Code=i;
                          tables.Add(table);
                      }
                      using (var context=new PgModel.testdbContext())
                      {
                          try
                          {
          
                              stopwatch.Start();
                              context.Database.BeginTransaction();
                              context.TestTables.AddRange(tables);
                              context.SaveChanges();
                              context.Database.CommitTransaction();
                              stopwatch.Stop();
                              sb.Append($"第{loop}輪插入100000條到【PostgreSQL】數據庫【成功】:耗時{stopwatch.ElapsedMilliseconds} ms...");
          
                          }
                          catch (Exception ex)
                          {
                              context.Database.RollbackTransaction();
                              stopwatch.Stop();
                              sb.Append($"第{loop}輪插入100000條到【PostgreSQL】數據庫【失敗】:耗時{stopwatch.ElapsedMilliseconds} ms...");
                          }
                          finally
                          {
                          }
                      }
          
                      return sb.ToString();
                  }
                  private String TestOracleUpdate()
                  {
                      StringBuilder sb=new();
                      Stopwatch stopwatch=new();
                     
                      using (var context=new OraModel.ModelContext())
                      {
                          
                          var datas=context.TestTables.OrderBy(x=>x.Code).Take(10000);
                          context.Database.BeginTransaction();
                          foreach (var value in datas)
                          {
                              value.Message=$"數據變更,code={value.Code}";
                          }
                          try
                          {
                              stopwatch.Start();
                              context.TestTables.UpdateRange(datas);
                              context.SaveChanges();
                              context.Database.CommitTransaction();
                              stopwatch.Stop();
                              sb.Append($"批量更新【Oracle】數據庫10000條【成功】:耗時{stopwatch.ElapsedMilliseconds} ms...");
                              
                          }
                          catch (Exception ex)
                          {
                              context.Database.RollbackTransaction();
                              stopwatch.Stop();
                              sb.Append($"批量更新【Oracle】數據庫10000條【失敗】:耗時{stopwatch.ElapsedMilliseconds} ms...");
                          }
                          finally
                          {
                          }
                      }
          
                      return sb.ToString();
                  }
                  private String TestMysqlUpdate(int loop)
                  {
                      StringBuilder sb=new();
                      Stopwatch stopwatch=new();
                      using (var context=new MyModel.testdbContext())
                      {
          
                          var datas=context.TestTables.OrderBy(x=> x.Code).Skip(loop*50000).Take(50000);
                          context.Database.BeginTransaction();
                          foreach (var value in datas)
                          {
                              value.Message=$"數據變更,code={value.Code}";
                          }
                          try
                          {
                              stopwatch.Start();
                              context.TestTables.UpdateRange(datas);
                              context.SaveChanges();
                              context.Database.CommitTransaction();
                              stopwatch.Stop();
                              sb.Append($"批量更新【MySQL】數據庫50000條【成功】:耗時{stopwatch.ElapsedMilliseconds} ms...");
          
                          }
                          catch (Exception ex)
                          {
                              context.Database.RollbackTransaction();
                              stopwatch.Stop();
                              sb.Append($"批量更新【MySQL】數據庫50000條【失敗】:耗時{stopwatch.ElapsedMilliseconds} ms...");
                          }
                          finally
                          {
                          }
                      }
          
                      return sb.ToString();
                  }
                  private String TestPostgreSQLUpdate(int loop)
                  {
                      StringBuilder sb=new();
                      Stopwatch stopwatch=new();
                      using (var context=new PgModel.testdbContext())
                      {
          
                          var datas=context.TestTables.OrderBy(x=> x.Code).Skip(loop * 50000).Take(50000);
                          context.Database.BeginTransaction();
                          foreach (var value in datas)
                          {
                              value.Message=$"數據變更,code={value.Code}";
                          }
                          try
                          {
                              stopwatch.Start();
                              context.TestTables.UpdateRange(datas);
                              context.SaveChanges();
                              context.Database.CommitTransaction();
                              stopwatch.Stop();
                              sb.Append($"第{loop}輪 批量更新【PostgreSQL】數據庫50000條【成功】:耗時{stopwatch.ElapsedMilliseconds} ms...");
          
                          }
                          catch (Exception ex)
                          {
                              context.Database.RollbackTransaction();
                              stopwatch.Stop();
                              sb.Append($"第{loop}輪 批量更新【PostgreSQL】數據庫50000條【失敗】:耗時{stopwatch.ElapsedMilliseconds} ms...");
                          }
                          finally
                          {
                          }
                      }
          
                      return sb.ToString();
                  }
          
          
          
              }

          以上測試至此就結束了。結論可能有點尷尬,也許跟環境配置有關,也可能跟ef core操作數據庫的支持與實現有關。并且當前僅在單表環境下測試,并沒有通過多表測試、存過測試、壓力測試等,結果僅供娛樂和參考。同時歡迎各位大佬們提供更多測試內容,也歡迎各位大佬轉發或評論或點贊等一鍵三連。

          本文原鏈接:https://www.cnblogs.com/weskynet/p/16097151.html


          果你不了解python,可以先了解python的簡單用法。不過人郵君相信,在座的各位都是大佬,我們直接介紹操作。

          第一部分,我們先來介紹python與mysql如何完成數據交互:

          python 與 mysql 實現交互的過程,通常分為:建立連接、把sql語句定義為字符串,提交指令、關閉連接

          核心的技能在于 sql語句;除了定義sql語句,其余3個處理都是固定的寫法。接下來,人郵君結合《MySQL是怎樣運行的》這本書,Linux環境為主,為大家進行說明。

          MySQL是怎樣運行的 從根兒上理解MySQL

          MySQL是怎樣運行的 從根兒上理解MySQL
          ¥49.5
          購買
          <script src="http://mp.toutiao.com/mp/agw/mass_profit/pc_product_promotions_js?item_id=6909291449641075203"></script>

          首先來看第一步,安裝 MySQL 數據庫:

          如果你想要使用python操作MySQL數據庫,就必須先要安裝pymysql庫,這個庫的安裝很簡單;

          第二步,pymysql 模塊安裝與使用:

          MySQL-python驅動,是python 操作mysql必不可少的模塊。

          下載MySQL-python-1.2.5.zip 文件之后直接解壓。進入MySQL-python-1.2.5目錄:

          >>python setup.py install

          下載地址:https://pypi.python.org/pypi/MySQL-python/

          第三步,python與mysql的交互實現:

          1)連接

          pymysql .connect () 函數:連接數據庫

          使用 pymysql 的 connect() 方法連接數據庫,涉及到幾個參數,具體代表意義如下:

          host:MySQL服務的地址,若數據庫在本地上,使用 localhost 或者127.0.0.1。如果在其它服務器上,則寫對應的 IP地址

          port:服務的端口號,默認為3306,不寫則為默認值。

          user:登錄數據庫的用戶名

          passwd:登錄 MySQL 的密碼

          db:數據庫名

          charset:設置為 utf8 編碼,解決存漢字亂碼問題

          eg:

          # 導入模塊
          import pymysql
          # 打開數據庫連接
          conn=pymysql.connect(
              host="127.0.0.1",
              user="root",
              password="123456",
              database="test_db",
              charset="utf8")
          print(conn)
          print(type(conn))

          輸出結果顯示如下:表面數據庫連接成功

          詳細可以參考

          https://www.cnblogs.com/qjj19931230/p/12550384.html?utm_source=tuicool

          這里要強調的是,除了上面的連接方式,還有其他的連接。在《MySQL是怎樣運行的》這本書中,介紹到,mysql連接分為內連接和外連接。內外連接的根本區別是在驅動表中記錄不符合ON子句中的連接條件時,內連接不會把該記錄加入到最后的結果集中,而外連接會。外連接分為左(外)連接和右(外)連接。


          三種鏈接方式如下圖所示:

          2)獲取游標

          conn.cursor():獲取游標

          對數據庫進行操作,只連接數據庫是不夠的,還需要獲取操作數據庫的游標,才能進行后續的操作。游標的主要作用是用來接收數據庫操作后的返回結果,比如數據查詢、插入和刪除等。通過獲取到的數據庫連接實例 conn 下的 cursor() 方法來創建游標,如下:

          # 導入模塊
          import pymysql
          # 打開數據庫連接
          conn=pymysql.connect(
              host="127.0.0.1",
              user="root",
              password="123456",
              database="test_db",
              charset="utf8")
          # print(conn)
          # print(type(conn))
          # 獲取連接下的游標
          cursor_test=conn.cursor()
          print(cursor_test)

          3)數據庫操作

          • 創建表
          import pymysql
          # 打開數據庫連接
          conn=pymysql.connect(
              host="127.0.0.1",
              user="root",
              password="123456",
              database="test_db",
              charset="utf8")
          # 獲取連接下的游標
          cursor_test=conn.cursor()
          # 使用 execute() 方法執行 SQL,如果表存在則刪除
          cursor_test.execute("DROP TABLE IF EXISTS EMPLOYEE")
          # 使用預處理語句創建表
          sql="""CREATE TABLE user1 (
                   FIRST_NAME  CHAR(20) NOT NULL,
                   LAST_NAME  CHAR(20),
                   AGE INT,  
                   SEX CHAR(1),
                   INCOME FLOAT )"""
          cursor_test.execute(sql)
          # 關閉數據庫連接
          conn.close()

          如下所示數據庫表創建成功:

          mysql> desc user1;
          +------------+----------+------+-----+---------+-------+
          | Field      | Type     | Null | Key | Default | Extra |
          +------------+----------+------+-----+---------+-------+
          | FIRST_NAME | char(20) | NO   |     | NULL    |       |
          | LAST_NAME  | char(20) | YES  |     | NULL    |       |
          | AGE        | int(11)  | YES  |     | NULL    |       |
          | SEX        | char(1)  | YES  |     | NULL    |       |
          | INCOME     | float    | YES  |     | NULL    |       |
          +------------+----------+------+-----+---------+-------+
          5 rows in set (0.00 sec)
          • 插入數據
          import pymysql
          # 打開數據庫連接
          conn=pymysql.connect(
              host="127.0.0.1",
              user="root",
              password="123456",
              database="test_db",
              charset="utf8")
          # 獲取連接下的游標
          cursor_test=conn.cursor()
          # 使用預處理語句創建表
          sql="""INSERT INTO user1(FIRST_NAME,
                   LAST_NAME, AGE, SEX, INCOME)
                   VALUES ('Fei', 'Fei', 20, 'M', 1000)"""
          try:
             # 執行sql語句
             cursor_test.execute(sql)
             # 提交到數據庫執行
             conn.commit()
          except:
             # 如果發生錯誤則回滾
             conn.rollback()
          # 關閉數據庫連接
          conn.close()
          • 查詢數據
          import pymysql
          # 打開數據庫連接
          conn=pymysql.connect(
              host="127.0.0.1",
              user="root",
              password="123456",
              database="test_db",
              charset="utf8")
          # 獲取連接下的游標
          cursor_test=conn.cursor()
          sql="""
              select * from user1"""
          try:
              # 執行 sql 語句
              cursor_test.execute(sql)
              # 顯示出所有數據
              data_result=cursor_test.fetchall()
              for row in data_result:
                  fname=row[0]
                  lname=row[1]
                  age=row[2]
                  sex=row[3]
                  income=row[4]
                  # 打印結果
                  print("fname=%s,lname=%s,age=%s,sex=%s,income=%s" % \
                        (fname, lname, age, sex, income))
          except:
              print("Error: unable to fetch data")
          # 關閉數據庫連接
          conn.close()
          • 刪除操作
          # 導入模塊
          import pymysql
          # 打開數據庫連接
          conn=pymysql.connect(
              host="127.0.0.1",
              user="root",
              password="123456",
              database="test_db",
              charset="utf8")
          # print(conn)
          # print(type(conn))
          # 獲取連接下的游標
          cursor_test=conn.cursor()
          sql="DELETE * FROM user1"
          try:
              # 執行SQL語句
              cursor_test.execute(sql)
              # 提交到數據庫執行
              conn.commit()
          except:
              # 發生錯誤時回滾
              conn.rollback()
          # 關閉數據庫連接
          conn.close()

          第二部分,我們來介紹如何實現「大量」數據的交互?

          《MySQL是怎樣運行的》,作者小孩子4919強調,嵌套循環連接算法是指驅動表只訪問一次,但被驅動表卻可能會訪問多次,訪問次數取決于驅動表執行單表查詢后的結果集中有多少條記錄,大致過程如下:


          步驟1,選取驅動表,使用與驅動表相關的過濾條件,選取代價最低的單表訪問方法來執行對驅動表的單表查詢;

          步驟2,對步驟1中查詢驅動表得到的結果集中的每一條記錄,都分別到被驅動表中查找匹配的記錄。

          由于被驅動表可能會訪問多次,因此可以為被驅動表建立合適的索引以加快查詢速度。

          所以,如果被驅動表非常大,即需要完成大量的數據交換,多次訪問被驅動表可能導致很多次的磁盤I/O讀取操作,此時可以使用基于塊的嵌套循環連接算法來緩解由此造成的性能損耗。Mysql的設計者,提出了名為Join Buffer(連接緩沖區)的概念:

          有興趣的同學,建議根據書中詳細描述走一遍。

          此外,人郵君特別建議大家看看《MySQL是怎樣運行的》,它解決了“為什么這個SQL語句執行得這么慢?為什么我明明建立了索引,但是查詢計劃顯示沒用?為什么IN查詢中的參數一多就不使用索引了?為什么我的數據顯示成了亂碼?”等等每一位DBA和后端開發人員在與MySQL打交道時,所遇到的很多常見問題。除此之外,索引結構、MVCC、隔離級別的實現、鎖的使用等知識,也是求職人員在MySQL面試中躲不過去的高頻問題,作者都在書中給出了很詳細的介紹。

          MySQL是怎樣運行的 從根兒上理解MySQL


          這本書的初稿最初是以小冊的形式發布在掘金平臺上的,一經發布便得到大家的青睞,十分火爆!歷經兩年,現在終于成書,有興趣的小伙伴也可以去掘金圍觀~(小孩子4919 的個人主頁)

          從底層到應用,從基礎到進階,關于MySQL的一切,作者都在書中講解得非常清楚,幫助你從根兒上理解MySQL。


          主站蜘蛛池模板: 国产在线aaa片一区二区99| 波多野结衣一区二区三区| 91在线一区二区三区| 国产电影一区二区| 国产乱码精品一区二区三| 亚洲色精品VR一区区三区| 国产一区二区三区久久精品| 秋霞鲁丝片一区二区三区| 中文无码一区二区不卡αv| 亚洲AV综合色区无码一区| 一区二区三区在线播放视频| 国产综合无码一区二区色蜜蜜| 精品国产一区二区三区色欲| 一区二区三区视频在线| 日本欧洲视频一区| 在线观看午夜亚洲一区| 日韩人妻无码一区二区三区久久99 | 综合久久久久久中文字幕亚洲国产国产综合一区首| 毛片一区二区三区| 亚洲欧美日韩中文字幕在线一区 | 日韩在线一区二区三区免费视频| 国产成人欧美一区二区三区| 亚洲一区免费视频| 日本一区频道在线视频| 中文字幕av人妻少妇一区二区| 亚洲一区二区免费视频| 亚洲av无码一区二区三区观看 | 国模极品一区二区三区| 日韩在线一区二区三区视频| 国产成人一区二区三区免费视频| 色妞色视频一区二区三区四区 | 亚洲国产高清在线一区二区三区| 日本一区二区三区四区视频| 国产精品日韩一区二区三区| 四虎永久在线精品免费一区二区 | 精品无人乱码一区二区三区| 最新中文字幕一区| 一区二区不卡久久精品| 精品久久一区二区三区| 久久久久人妻一区精品性色av| 亚洲AV成人精品日韩一区|