MS_DotNetBatch - NetDevInfraWGinOSSConsortium/NetDevInfraWiki GitHub Wiki
- æ»ã
ADO.NET ã®ããŒã¿ãããã€ãã䜿çšãã .NET ããã°ã©ã ã§ã¯ã
倧éããŒã¿ãåŠçãããããéçºã«é©åããªãã±ãŒã¹ãããã
-
ADO.NET ã®ããŒã¿ãããã€ãã§ã¯ä»¥äžã®æ©èœããµããŒããããŠããªãã±ãŒã¹ãããã
ïŒ JDBC ãªã©ã®ããŒã¿ãããã€ãã«ã¯æšæºã§å®è£ ãããŠããæ©èœ- ãã§ããã»ãµã€ãºæå®ïŒãã§ããïŒ
- é åãã€ã³ãïŒãããæŽæ°ïŒ
-
OracleãHiRDB ã®ããŒã¿ãããã€ãã«ã€ããŠã¯ãµããŒããããŠãããã®ãããã
- ODP.NET
- ãã§ããã»ãµã€ãºæå®ïŒãã§ããïŒ
- é åãã€ã³ãïŒãããæŽæ°ïŒ
- HiRDB.NET
- é åãã€ã³ãïŒãããæŽæ°ïŒ
- ODP.NET
è£è¶³ïŒãã®ææã¯çŸåšãæŠãæ£ããïŒ: ãADO.NET ã«ã¯
ãã§ãã ãµã€ãºæå®ãšé åãã€ã³ãããªããââ
ãã®èšºæã¯æ¬ããŒãžã®åºçºç¹ã§ãããçŸåšãæŠãåœãŠã¯ãŸããããã§ãã ãµã€ãºïŒé åãã§ããïŒã ãµãŒããããäœè¡ãŸãšããŠåã£ãŠãããã JDBC: stmt.setFetchSize(1000) ODP.NET: cmd.FetchSize = 1024 * 1024ïŒãã€ãåäœïŒâ SqlClient: ãæå®ã§ããªãã â SQL Server 㯠TDS ã®ãã±ããåäœã§èªåçã«ãŸãšããŠéã â ãæå®ã§ããªãããå®è³ªçã«åé¡ã«ãªããªãã ãé åãã€ã³ãïŒãããæŽæ°ïŒã 1 åã®åŸåŸ©ã§ãè€æ°è¡ãæŽæ°ããã JDBC: addBatch() / executeBatch() ODP.NET: cmd.ArrayBindCount = 1000 â SqlClient: ããªãã â 代æ¿ã¯ SqlBulkCopy / ããŒãã«å€ãã©ã¡ãŒã¿ïŒåŸè¿°ïŒãªããã®å·®ãçãŸããã®ã:
ã»ADO.NET ã¯ãDataSet / DataAdapter ãäžå¿ãã«èšèšããã â ãåã£ãŠããŠãã¡ã¢ãªã§å å·¥ããŠãæžãæ»ããã¢ãã« â ãè¡åäœã®ã«ãŒãããåæã§ã¯ãªãã£ã ã»JDBC ã¯ãã«ãŒãœã«ãšãããããäžå¿ã«èšèšããã â 倧éããŒã¿ã®ãããåŠçãæ³å®å â èšèšææ³ã®éãã§ãããåªå£ã§ã¯ãªã â ãã ãããããåŠçã§ã¯ JDBC åã®æ¹ãçŽ çŽãâç§»è¡ã¡ã¢ïŒHiRDB.NET / ODP.NET ã®çŸæ³ïŒ:
ã»ODP.NET ã¯ãManaged / Core çããããã.NET 8 çã«å¯Ÿå¿ â Oracle.ManagedDataAccess.Core â ArrayBindCount ã¯çŸåšãå©çšå¯èœ â ã»HiRDB ã® .NET ãããã€ããç¶ç¶æäŸãããŠãã
DB ã«ããããINSERTãUPDATE ãªã©ã® SQL ãé£ç¶ããŠèšè¿°ããããšã¯å¯èœã
- 以äžã¯ãSQL Server ã®äŸ
INSERT INTO XXXX(xxx, yyy, zzz) VALUES(xxx, yyy, zzz);
INSERT INTO XXXX(xxx, yyy, zzz) VALUES(xxx, yyy, zzz);
INSERT INTO XXXX(xxx, yyy, zzz) VALUES(xxx, yyy, zzz);
ã»ã»ã»
UPDATE SET xxx=xxx, yyy=yyy, zzz=zzz, WHERE id = 1;
UPDATE SET xxx=xxx, yyy=yyy, zzz=zzz, WHERE id = 2;
UPDATE SET xxx=xxx, yyy=yyy, zzz=zzz, WHERE id = 3;
ã»ã»ã» - ãã ãããã€ã³ã倿°ã®æ°ã«å¶çŽãããããã
ãã©ã¡ã¿ã©ã€ãºãã»ã¯ãšãªã§ã®ããã©ã¡ã¿ããèšå®ãé£ãã
è£è¶³ïŒåæã®ææã¯ç確ãå¶çŽã®æ°å€ã瀺ãïŒ: ããã€ã³ã倿°ã®æ°ã«å¶çŽã
ããããããã©ã¡ã¿ãèšå®ãé£ããââãããæ±ºå®çãªå¶çŽã§ããããSQL Server ã®ãã©ã¡ãŒã¿æ°ã®äžéã ã¹ãã¢ã ããã·ãŒãžã£: 2,100 ã1 ãããã®ãã©ã¡ãŒã¿: 2,100ãâ â 1 è¡ 10 åãªãã210 è¡ãäžéã â ã1 äžä»¶ãäžæ¬ã§ãã¯äžå¯èœ ãOracleã ãã€ã³ã倿°ã®äžé㯠65,535ïŒå®è³ªçã«ã¯å¥ã®å¶çŽãå ã«æ¥ãïŒããã©ã¡ãŒã¿åããªããš SQL ã€ã³ãžã§ã¯ã·ã§ã³ãâ å€ãæååé£çµã§åã蟌ãã°ãã©ã¡ãŒã¿æ°ã®å¶çŽã¯åé¿ã§ãããã ã絶察ã«ãã£ãŠã¯ãªããªãã â SQL ã€ã³ãžã§ã¯ã·ã§ã³ â å®è¡ãã©ã³ã®ãã£ãã·ã¥ãå¹ããªãïŒãã©ã³ ãã£ãã·ã¥ã®æ±æïŒ â [SQL Serverã®å®è¡ãã©ã³](MS_SQLExecutionPlan) åç §ç§»è¡ã¡ã¢ïŒãµã³ãã«ã® SQL æ§æïŒ:
UPDATEæã
UPDATE SET ...ãšãªã£ãŠãããããŒãã«åãæ¬ ããŠãã
ïŒæ£ããã¯UPDATE XXXX SET ...ïŒã
ãŸããSETå¥ã®æ«å°Ÿã«äœåãªã«ã³ããããã
ç䌌ã³ãŒããšããŠã®èšèŒãšèªããããæ³šèšããŠããã
-
SQL Server 2005 ãããµããŒããããæ©èœã
-
.NET ã§ã¯ SQL CLR ãšèšãæ©æ§ãçšæãããŠãããã
- ã€ã³ããã»ã¹ã§åäœãããã®ã®
- ã«ãŒãœã«æäœããµããŒãããªã
ããããããåŠçã®çšéã§ã¯ãããŸãé åçãªãã®ã§ã¯ç¡ãã
-
ãŸããåæ§ã«ãµããŒããããŠããããŒã¿ãããã€ããéãããã
- SQL ServerïŒSQL CLRïŒ
- ODP.NETïŒ.NET ã¹ãã¢ãã»ããã·ãŒãžã£ïŒ
ïŒåŸè¿°ã® CLR ã¹ãã¢ã ããã·ãŒãžã£ ãåç §ïŒ
è£è¶³ïŒSQL CLR ã®çŸæ³ ââ åæã®å€æã¯æ£ããã£ãïŒ: ãããŸãé åçãª
ãã®ã§ã¯ç¡ãããšããåæã®è©äŸ¡ã¯ããã®åŸã®çµç·¯ããã劥åœã ã£ãããSQL CLR ã®çŸæ³ã ã»SQL Server ã§ã¯ãä»ã䜿ãããïŒãªã³ãã¬ãã¹ïŒ ã»ãAzure SQL Database ã§ã¯äœ¿ããªããâ â ã¯ã©ãŠãç§»è¡ã®é害ã«ãªã ã»SQL Server 2017 以éãæ¢å®ã§ãCLR strict securityããæå¹ â ãã¢ã»ã³ããªã«çœ²åãå¿ èŠãã«ãªããå°å ¥ã®æéãå¢ãã ã»æ¡çšäŸã¯åæã®æä»£ããããã«æžã£ãŠãããSQL CLR ãä»ãæå¹ãªçšéã ã»æ£èŠè¡šçŸïŒT-SQL ã«ã¯è²§åŒ±ãªãã¿ãŒã³ ããããããªãïŒ ã»è€éãªæåååŠçã»ç¬èªã®éèšé¢æ° ã»[æåã®ãã§ãã¯æ¹åŒ](MS_CharacterValidation) ã®ãããªæåã³ãŒãå€å® â ãããããè¡åäœã®å€æãã§ãããã«ãŒãœã«æäœã¯äžèŠ ãåããªãçšéã ã»ãããåŠçãã®ãã®ïŒåæã®ææã®éãïŒ ã»å€éšãªãœãŒã¹ãžã®ã¢ã¯ã»ã¹ïŒãã¡ã€ã«ãHTTPïŒ â UNSAFE ã¢ã»ã³ããªãå¿ èŠãDB ã®å®å®æ§ãæãªã â
-
INSERT ã§è€æ°ã®å€ãæå®ããããšãå¯èœãšãªã£ãïŒUPDATE ã¯é察å¿ïŒã
-
åæ§ã«ããã€ã³ã倿°ã®æ°ã«å¶çŽãããããã
ãã©ã¡ã¿ã©ã€ãºãã»ã¯ãšãªã§ã®ããã©ã¡ã¿ããèšå®ãé£ãã -
åè
- INSERT ã¹ããŒãã¡ã³ãã§è€æ°ã®å€ãæå® - æŸæ¬åŽå Blog ïŒSQL Server TipsïŒ
https://d.hatena.ne.jp/matu_tak/20100113/1263856222
- INSERT ã¹ããŒãã¡ã³ãã§è€æ°ã®å€ãæå® - æŸæ¬åŽå Blog ïŒSQL Server TipsïŒ
è£è¶³ïŒè¡ã³ã³ã¹ãã©ã¯ã¿ã®äžéïŒ:
INSERT ... VALUES (âŠ),(âŠ),(âŠ)ã¯
1 æããã 1,000 è¡ãäžéã§ããã
ãã©ã¡ãŒã¿æ°ã® 2,100 å¶çŽãšåããããšã
å®çšçã«ã¯æ°çŸè¡ãé床ã«ãªãããUPDATE ã®è€æ°è¡å¯Ÿå¿ã åæã®ãUPDATE ã¯é察å¿ãã¯æ£ãããã ãMERGE æããŸãã¯ãFROM å¥ä»ã UPDATEãã§ è€æ°è¡ããŸãšããŠæŽæ°ã§ãã â-- ããŒãã«å€ãã©ã¡ãŒã¿ + UPDATE ... FROMïŒçŸåšã®å®ç³ïŒ UPDATE t SET t.name = s.name, t.price = s.price FROM åå AS t JOIN @tvp AS s ON t.id = s.id;
-
SQL Server 2008 ãããããŒãã«å€ãã©ã¡ã¿ãšãããã©ã¡ã¿ãèšå®å¯èœã«ãªã£ãŠããã
-
ããŒãã«å€ãã©ã¡ã¿ã¯ã以äžã®åãšããŠãããã°ã©ã åŽããæå®ã§ããã
-
.NET
- DataTable
- DbDataReader
- IEnumerable<T>
-
SQL CLR
- SqlDataRecord
-
-
åè
-
SQL Server 2008 ã®ããŒãã«å€ãã©ã¡ãŒã¿ (ADO.NET)
https://learn.microsoft.com/ja-jp/dotnet/framework/data/adonet/sql/table-valued-parameters -
SQL Serverã«ãããTable-Valuedãã©ã¡ãŒã¿
https://www.infoq.com/jp/news/2008/08/table-valued-param -
Microsoft Docs
- ããŒãã«å€ãã©ã¡ãŒã¿ãŒ
https://learn.microsoft.com/ja-jp/dotnet/framework/data/adonet/sql/table-valued-parameters - ããŒãã«å€ãã©ã¡ãŒã¿ãŒã®äœ¿çš (ããŒã¿ããŒã¹ ãšã³ãžã³)
https://learn.microsoft.com/ja-jp/sql/relational-databases/tables/use-table-valued-parameters-database-engine
- ããŒãã«å€ãã©ã¡ãŒã¿ãŒ
-
è£è¶³ïŒããŒãã«å€ãã©ã¡ãŒã¿ããåæã®åé¡ãžã®è§£ã«ãªãïŒ: æ¬ããŒãžã®
ããã©ã¡ãŒã¿æ°ã®å¶çŽã§ãããæŽæ°ãã§ããªãããšãã課é¡ã«å¯Ÿãã
ããŒãã«å€ãã©ã¡ãŒã¿ïŒTVPïŒãæ£é¢ããçããã-- â ãŠãŒã¶ãŒå®çŸ©ããŒãã«åãäœãïŒ1 åã ãïŒ CREATE TYPE dbo.OrderTvp AS TABLE ( Id INT NOT NULL PRIMARY KEY, Name NVARCHAR(50) NOT NULL, Price DECIMAL(18,2) NOT NULL );// â¡ .NET ããæž¡ãïŒãã©ã¡ãŒã¿ã¯ã1 åãã§æžãïŒâ var p = cmd.Parameters.AddWithValue("@tvp", table); // DataTable p.SqlDbType = SqlDbType.Structured; p.TypeName = "dbo.OrderTvp";-- ⢠ã¹ãã¢ãåŽã§ãéåãšããŠãæ±ãã INSERT INTO 泚æ (Id, Name, Price) SELECT Id, Name, Price FROM @tvp; -- æŽæ°ãå¯èœïŒåæã®ãUPDATE ã¯é察å¿ããžã®åçïŒâ UPDATE t SET t.Price = s.Price FROM 泚æ t JOIN @tvp s ON t.Id = s.Id; -- MERGE ã§ INSERT/UPDATE/DELETE ãäžåºŠã« MERGE 泚æ AS t USING @tvp AS s ON t.Id = s.Id WHEN MATCHED THEN UPDATE SET t.Price = s.Price WHEN NOT MATCHED THEN INSERT (Id, Name, Price) VALUES (s.Id, s.Name, s.Price);ãTVP ã®å©ç¹ã ã»ããã©ã¡ãŒã¿æ°ã®å¶çŽãåé¿ã§ãããâ ã»åä»ãïŒåã®åãå®çŸ©ãããïŒ ã»å®è¡ãã©ã³ãåå©çšããã ã»SQL ã€ã³ãžã§ã¯ã·ã§ã³ã®äœå°ããªã ã»ãéåæŒç®ãšããŠæžãããïŒ è¡ã«ãŒããæ¶ãã ãTVP ã®æ³šæç¹ã ã»èªã¿åãå°çšïŒ@tvp ã UPDATE ã§ããªãïŒ ã»çµ±èšæ å ±ãæããªãããããè¡æ°ã®èŠç©ãã 1 è¡åºå®ãã«ãªã â 倧éããŒã¿ã§ã¯ãã©ã³ãæªåããã â OPTION (RECOMPILE) ãæ€èšãã ã»æ°äžè¡ãè¶ ãããªããSqlBulkCopyãã®æ¹ãéã â
IEnumerable<SqlDataRecord>ã䜿ããšã¡ã¢ãªãç¯çŽã§ããã// DataTable ãšéãããå šä»¶ãã¡ã¢ãªã«èŒããã«ãã¹ããªãŒã ã§æž¡ãã â static IEnumerable<SqlDataRecord> ToRecords(IEnumerable<Order> orders) { var meta = new[] { new SqlMetaData("Id", SqlDbType.Int), new SqlMetaData("Name", SqlDbType.NVarChar, 50), }; var rec = new SqlDataRecord(meta); foreach (var o in orders) { rec.SetInt32(0, o.Id); rec.SetString(1, o.Name); yield return rec; // â åãã€ã³ã¹ã¿ã³ã¹ã䜿ãåã } }
ããã§ããæ©èœã®ä»£æ¿ãåŠçæ¹åŒã®æ€èšŒ
-
SQL Server ã®ããŒã¿ãããã€ãã䜿çšã
-
ãã§ããæ©èœã®ä»£æ¿
-
ãã§ããæ©èœã代æ¿ããããã«ãã¯ããã«äž»ããŒã»ã»ããã ããååŸãã
ã³ãããã»ã€ã³ã¿ãŒãã«åãIN å¥ã«äž»ããŒãæå®ããŠçµæã»ãããåå²ååŸ
ããããšã§ãã§ããæ©èœã®ä»£æ¿ãšããæ¹åŒãããã -
ãã ãããã®éã®æ€çŽ¢åŠçæ§èœãèæ ®ãããšã
åç §å ããŒãã«ã«ã€ã³ããã¯ã¹ã貌ãããŠããå¿ èŠããããªã©ã
æ¬åŠçæ¹åŒïŒç䌌ãã§ããæ¹åŒïŒãæ¡çšããäžã§ã®å¶çŽãããã
-
è£è¶³ïŒãã®ãç䌌ãã§ããæ¹åŒãã®è©äŸ¡ïŒ: å®åçãªå·¥å€«ã ãã
çŸåšã¯ããçŽ çŽãªæ¹æ³ãããã®ã§äœµèšããŠããããç䌌ãã§ããæ¹åŒïŒåæïŒã â äž»ããŒã ããå šä»¶ååŸ â¡ ã³ãããåäœïŒäŸïŒ1000 ä»¶ïŒã〠IN å¥ã§æ¬äœãååŸ â¢ åŠçããŠã³ããã ãå©ç¹ã ã»ã³ãããåäœãæç¢ºïŒéäžã§å€±æããŠãåéããããïŒâ ã»æ¥ç¶ãé·æéä¿æããªã ãæ¬ ç¹ã ã»äž»ããŒã®å šä»¶ååŸãå¿ èŠïŒä»¶æ°ãå€ããšã¡ã¢ãªãé£ãïŒ ã»IN å¥ã®ãã©ã¡ãŒã¿æ°å¶çŽïŒ2,100ïŒ ã»ããŒãã«ãã2 åèªããããšã«ãªã ã»ã€ã³ããã¯ã¹ãå¿ é ïŒåæã®ææã®éãïŒçŸåšã®ä»£æ¿:
-- â ããŒã»ãã ããŒãžã³ã°ïŒæšå¥šïŒâ SELECT TOP (1000) * FROM æçް WHERE Id > @lastId -- â ååã®æåŸã®ããŒããç¶ãã ORDER BY Id; -- ã»IN å¥ãäžèŠããã©ã¡ãŒã¿ã¯ 1 å -- ã»OFFSET/FETCH ããéãïŒæ·±ãããŒãžã§å£åããªãïŒ -- ã»äžæã»åéã容æïŒ@lastId ãä¿åããã ãïŒ// â¡ ãããã DataReader ã§ãã¹ããªãŒã èªã¿ããã using var reader = await cmd.ExecuteReaderAsync( CommandBehavior.SequentialAccess); while (await reader.ReadAsync()) { // 1 è¡ãã€åŠçããããå šä»¶ãã¡ã¢ãªã«èŒããªããâ }ãDataReader ã䜿ãããªãããããæãçŽ çŽã ã»SqlClient ã¯å éšã§ãã±ããåäœã«ãŸãšããŠåä¿¡ããŠãã â æç€ºçãªãã§ãã ãµã€ãºæå®ããªããŠãååã«éã ã»åæã®ããã§ããæ©èœããªãããšãã課é¡ã¯ã ãSQL Server ã«éãã°å®è³ªçãªåé¡ã«ãªããªããâ ããã ãã ã»èªã¿ãªããåãæ¥ç¶ã§æŽæ°ã¯ã§ããªãïŒå¥æ¥ç¶ãèŠãïŒ ã»é·æéã®èªã¿åãã¯ãããã¯ã»ããŒãžã§ã³ã¹ãã¢ãã«åœ±é¿ãã â ã¹ãããã·ã§ããåé¢ããŸãã¯åå²èªã¿ãæ€èš
-
100 äžä»¶ã®ããŒã¿ã® SELECT â INSERT åŠçãäžèšã®ç䌌ãã§ããæ¹åŒã§èšè¿°ããå Žåã
Transact-SQL ã§ã¯ 15 åçšåºŠã§ãã£ãåŠçãã.NET ã§ãã»ãŒ â ã®æéã§åŠçãå®äºããã -
ãŸããŸãã®æ§èœã§ããããã®æ¹åŒãæ¡çšã§ããæ¡ä»¶äžã§ããã°
åŠçããŒã¿éãäžèŠæš¡ã®ãããã§ãã£ãŠã .NET ã§å®è£ å¯èœãšèããã
-
ãŸãäžèšã¯ã.NET ã®ãããããã°ã©ã ããããã¯ãŒã¯äžã§ã¯ãªãã
DB ãµãŒãäžã«çŽæ¥é 眮ããå Žåã®æ§èœæ å ±ã§ããã -
ãããã¯ãŒã¯çµç±ã®å Žåã¯ãç¹ã«æŽæ°ã©ãŠã³ãã»ããªããã®ããäœéã«ãªãã
ãããã¯ãŒã¯ã®äœ¿çšç¶æ³ã«ãã£ãŠã¯éåžžã«äœéã«ãªãäºãããããæ³šæãå¿ èŠã§ããã
è£è¶³ïŒãã®æ€èšŒã®äŸ¡å€ãšãçŸåšã®æ°åæïŒ: 宿ž¬ããŠæ¯èŒããŠããç¹ã
æ¬ããŒãžã®äŸ¡å€ã§ãããçµè«ã劥åœã§ããã
ã©ãŠã³ãããªãããæ¯é çãšããææã¯ãçŸåšãå€ãããªãæéèŠç¹ã§ãããããªãã©ãŠã³ãããªãããå¹ãã®ãã 100 äžä»¶ à 1 ä»¶ã〠INSERT = 100 äžåã®åŸåŸ© åäžãµãŒãå ïŒå ±æã¡ã¢ãª / Named PipesïŒ: åŸåŸ© â 0.05ms â 100 äž Ã 0.05ms = ãçŽ 50 ç§ã LAN çµç±ïŒTCPãRTT 0.5msïŒ: â 100 äž Ã 0.5ms = ãçŽ 8 åãâ ã¯ã©ãŠãè¶ãïŒRTT 5msïŒ: â 100 äž Ã 5ms = ãçŽ 83 åãâ â â ã1 ä»¶ãã€åŠçããèšèšã¯ãè·é¢ãé¢ãããšç Žç¶»ãããããããã£ãŠã ã»åæã®ãDB ãµãŒãäžã«çŽæ¥é 眮ãã¯ã åœæãšããŠã¯ãæ£ããåé¿çãâ ã»çŸåšã®ã¯ã©ãŠãç°å¢ã§ã¯ç©ççã«åå± ã§ããªãããã ãåŸåŸ©åæ°ãã®ãã®ãæžãããèšèšãå¿ é ã«ãªã â SqlBulkCopyãTVPãMERGEããããæŽæ°çŸåšã®æ°åæïŒåèïŒ:
100 äžè¡ã® INSERTïŒSQL ServerãåäžãªãŒãžã§ã³ïŒ 1 ä»¶ã〠ExecuteNonQuery ⊠æ°åå TVPïŒ1000 ä»¶ãã€ïŒ ⊠æ°å ãSqlBulkCopyã âŠ ãæ°åç§ãâ BULK INSERT / bcpïŒãã¡ã€ã«ïŒ ⊠æ°åç§
.NET ããã°ã©ã ã§ãã倧éããŒã¿ãåŠçå¯èœ
ïŒãã ãããããã¯ãŒã¯çµç±ã¯ãªãŒããŒãããã倧ããã®ã§æ³šæïŒã
SQL CLR ã®æ¡çšãèããããããæ¡çšäŸãå°ãªãã®ã§ã
-
åºæ¬çã«ã¯ã
- SQL Server ã§ããã° Transact-SQL
- Oracle ã§ããã° PL/SQL
ãè¯ããšèããïŒåŠçæ¹åŒçµ±äžã®æšæºåã®æå³ãå«ããŠïŒã
-
æåååŠççã«ã¢ããã³ããŒãžããããšèšãããŠãããã
ã«ãŒãœã«æäœããµããŒãããŠããªãç¹ã倧ããªæ¬ ç¹ãšãªã£ãŠããã
.NET ã§ã¯ã¹ããŒãžã³ã°ã»ãã§ãŒãºãå®è£ ããŠå€§éããŒã¿ç»é²ã¯ DB æ©èœã«ä»»ãããªã©ã
è£è¶³ïŒãã®çµè«ãçŸåšã®å®ç³ãã®ãã®ïŒ: ãã¹ããŒãžã³ã° ãã§ãŒãºãå®è£ ããŠ
倧éããŒã¿ç»é²ã¯ DB æ©èœã«ä»»ãããââ
ãããçŸåšã® ELTïŒExtract-Load-TransformïŒã®èãæ¹ã§ããã
20 幎è¿ãçµã£ãŠãæ£ããããã¹ããŒãžã³ã°æ¹åŒãâ â .NET ⊠ããŒã¿ãååŸã»æŽåœ¢ãããäžæ¬ã§æµã蟌ãã SqlBulkCopy / BULK INSERT / bcp â â¡ ã¹ããŒãžã³ã° ããŒãã«ïŒäžæçãªåãç¿ïŒ â ⢠T-SQL ⊠ãéåæŒç®ã§ãæ¬ããŒãã«ãžåæ MERGE / INSERT ... SELECT / UPDATE ... FROM â ãè¡ã«ãŒããå®å šã«æ¶ããã â åŸåŸ©åæ°ããæ°åãã«ãªã â 倿ããžãã¯ã¯ DB ãšã³ãžã³ãæé©åããŠããã// â SqlBulkCopyïŒ.NET ããæéã§æµãèŸŒãææ®µïŒâ using var bulk = new SqlBulkCopy(conn, SqlBulkCopyOptions.TableLock, tran) { DestinationTableName = "dbo.Staging_泚æ", BatchSize = 10000, BulkCopyTimeout = 0, // ç¡å¶é EnableStreaming = true, // â IDataReader ããã¹ããªãŒã ã§ }; await bulk.WriteToServerAsync(reader);ãSqlBulkCopy ãéãããèŠç¹ã ã»TableLock ãªãã·ã§ã³ïŒä»ã®æŽæ°ããªããªãïŒâ ã»ãã€ã³ããã¯ã¹ãèœãšããŠããæµããåŸã§è²ŒãçŽãã ã»åŸ©æ§ã¢ãã«ãäžæ¬ãã°ã«ããïŒå¯èœãªãïŒ ã»BatchSize ã調æŽããïŒå€§ãããããšãã°ãèšããïŒ â [SQL Serverã®å€§éããŒã¿åŠçæ§èœ](MS_SQLServerBulkDataPerformance) åç §åæã®ãåŠçæ¹åŒçµ±äžã®æšæºåã®æå³ãå«ããŠããšããçç±ä»ããéèŠã§ããã
ãæè¡çãªåªå£ãããçµ±äžã®äŸ¡å€ãåãããšãããã ã»SQL CLR ã 1 ç®æã ã䜿ããšã ããã® 1 ç®æã®ããã« CLR ã®ç¥èã»é 眮æé ã»çœ²åãèŠãã ã»é害æã«ãã©ãã«åŠçãããããã忣ãã â [Windowsã®å€å](MS_WindowsGaiji) ã®ã顧客èŠä»¶ã«å ãããšåæ§ã æè¡éžå®ã¯ãéçšã®ã³ã¹ãããŸã§å«ããŠå€æãã â
- COBOLïŒæãã䜿ãããŠããå®çžŸãå€ãïŒ
- åçš®ã¹ãã¢ãïŒé床éèŠã倧éããŒã¿ïŒ
Java ã .NET ã§ã®å®çžŸã¯äžèšã«æ¯ã¹ããšå€ãã¯ç¡ããšæããŸããã
æè¿ã¯ãSpring Batch ãªã©ã® Batch Framework ã®ç»å Žã§ã
Java ã§ãããããæžãããããšãå¢ããŠããŠãŠããŸãã
-
Java
-
å€éå
- åºæ¬ãã«ãã¹ã¬ããåã§å€éåã
- ã¡ã¢ãªäœ¿çšéïŒå¶éïŒã®é¢ä¿ã§ããã«ãã¹ã¬ããåã§ã¯ãªã
ããã»ã¹ã®å€éèµ·åã§å¯Ÿå¿ããããšãããããã§ãã
-
Batch Framework
ãã ãBatch Framework ããå°ã ãªãŒããŒã¹ããã¯ã®æ§ã§
ããããçè§£ããŠäœ¿ãããªãã®ãé£ãããããã§ãã
-
-
.NET
- å€éå
- ãã«ãã¹ã¬ããåãEXE å€éèµ·åã®ãäž¡æ¹ãå¯èœã§ãã
- .NET ã ãšãEXE å€éèµ·åã®æ¹ãäžè¬çã ãšæããŸãã
ãã«ãã¹ã¬ããåãå¿ èŠãšãªãã±ãŒã¹ã¯ãããŸãæãã€ããŸããã
- å€éå
è£è¶³ïŒ.NET ã§ã®ãããå®è£ ã®çŸåšïŒ: ã.NET ã«ã¯ Batch Framework ããªãã
ãšããåœæã®ç¶æ³ã¯ãçŸåšã¯å€ãã£ãŠããã
ææ®µ å 容 Worker Service .NET æšæºã®ãã³ãã¬ãŒããDIã»èšå®ã»ãã°ã»graceful shutdown 蟌㿠â IHostedService/BackgroundServiceåžžé§åŠçã®æšæºçãªåœ¢ èªäœCUIïŒCLIïŒã®è©± åŒæ°ãåã㊠1 åå®è¡ããããã Hangfire / Quartz.NET ãžã§ãã®ã¹ã±ãžã¥ãŒã«ã»åå®è¡ã»å¯èŠå Azure FunctionsïŒã¿ã€ããŒïŒ ãµãŒããŒã¬ã¹ã®ãããïŒFaaS configïŒ Azure Batch / Container Apps Jobs å€§èŠæš¡ãªäžŠåå®è¡ // Worker ServiceïŒçŸåšã®æšæºåœ¢ïŒ var builder = Host.CreateApplicationBuilder(args); builder.Services.AddHostedService<ImportWorker>(); builder.Services.AddDbContext<AppDbContext>(/* ... */); var host = builder.Build(); await host.RunAsync();ãWorker Service ã®å©ç¹ã ã»[.NET Core ã«ããã DI](MS_DotNetCoreDI) ããã®ãŸãŸäœ¿ãã ã»[.NETã®ãã°](MS_DotNetLogging) ã® ILogger ã䜿ãã ã»[FaaS config](MS_FaaSConfig) ãšåãæ§æã®ä»çµã¿ ã»ãSIGTERM ãåããŠç¶ºéºã«æ¢ãŸããâ â ã³ã³ããéçšã§å¿ é â [ããã»ã¹ééä¿¡](MS_InterProcessCommunication) ã® PosixSignalRegistration åç §ãEXE å€éèµ·åã®æ¹ãäžè¬çããšããåæã®ææã¯ä»ã劥åœã§ããã
ããªãå€éããã»ã¹ã奜ãŸãããã ã»1 ã€ãèœã¡ãŠãä»ã«åœ±é¿ããªãïŒé害ã®åé¢ïŒâ ã»OS / ãžã§ã ã¹ã±ãžã¥ãŒã©ã§å¶åŸ¡ã§ãã ã»ã¡ã¢ãªã®äžéãåå¥ã«æãŠã ã»å®è£ ãåçŽïŒå ±æç¶æ ããªãïŒ ãçŸåšã®ã³ã³ããéçšã§ãåãçºæ³ã ã»1 ã³ã³ãã 1 ããã»ã¹ ã»Kubernetes ã® Job / CronJob ã§äžŠå床ãæå®ãã ã»ãã¥ãŒããåãèšèšã«ããã°ããèªç¶ã«ã¹ã±ãŒã«ãããâãããèšèšã§æŒãããã¹ãç¹ïŒèšèªãåããªãïŒ:
â ãåå®è¡ã§ããããïŒåªçæ§ïŒâ â éäžã§èœã¡ãŠåå®è¡ããŠããäºéç»é²ã«ãªããªãã â åŠçæžã¿ãã©ã°ããŸã㯠MERGE ã§æ ä¿ãã â¡ ãäžæã»åéã§ãããã â ããŒã»ãã ããŒãžã³ã°ïŒåè¿°ïŒãšçžæ§ãè¯ã ⢠ãã³ãããåäœã â 倧ãããããšãã°ãèšãã¿ãããŒã«ããã¯ãéã â å°ãããããšåŸåŸ©ãå¢ãã ⣠ãå€éèµ·åã®é²æ¢ã â ååä»ã MutexãDB ã®ãã㯠ããŒãã«ã忣ãã㯠†ã鲿ãšçµæãèšé²ããã â äœä»¶åŠçããŠäœä»¶å€±æãããïŒ[.NETã®ãã°](MS_DotNetLogging)ïŒ â¥ ãç°åžžæã®éç¥ã â çµäºã³ãŒããè¿ããç£èŠåºç€ã§æŸã
Tags: ç§»è¡, ããŒã¿ã¢ã¯ã»ã¹, ADO.NET, Entity Framework, æ§èœ