小议SQLServer批量更新的优化
听全老大的 JDBC 课的时候,听到一节是讲在利用 JDBC 中处理批量更新oracle数据时候的特性,让我很为 JDBC 的特性感的兴奋,利用这个特性可以在批量更新数据的时候不同往常一样每次都需要传送完成的 SQL 语句到数据库中。其中示范代码如下 : 1 import java.s
听全老大的JDBC课的时候,听到一节是讲在利用JDBC中处理批量更新oracle数据时候的特性,让我很为JDBC的特性感的兴奋,利用这个特性可以在批量更新数据的时候不同往常一样每次都需要传送完成的SQL语句到数据库中。其中示范代码如下:
1 import java.sql.*; 2 3 publicclass BatchUpdates 4 { 5 publicstaticvoid main(String[] args) 6 { 7 Connection conn =null; 8 Statement stmt =null; 9 PreparedStatement pstmt =null; 10 ResultSet rset =null; 11 int i =0; 12 13 try 14 { 15 DriverManager.registerDriver(new oracle.jdbc.OracleDriver()); 16 17 String url ="jdbc:oracle:oci8:@"; 18 try { 19 //检查是否配置JDBC环境变量 20 String url1 = System.getProperty("JDBC_URL"); 21 if (url1 !=null) 22 url = url1; 23 } catch (Exception e) { 24 //如果是在集成开发环境导入了JDBC的话可以注释这句 25 } 26 27 // 连接到数据库用 scott 28 conn = DriverManager.getConnection (url, "scott", "tiger"); 29 30 stmt = conn.createStatement(); 31 try { stmt.execute( 32 "create table mytest_table (col1 number, col2 varchar2(20))"); 33 } catch (Exception e1) {} 34 35 // 36 // 批量插入新值. 37 // 38 pstmt = conn.prepareStatement("insert into mytest_table values (?, ?)"); 39 40 pstmt.setInt(1, 1); 41 pstmt.setString(2, "row 1"); 42 pstmt.addBatch(); 43 44 pstmt.setInt(1, 2); 45 pstmt.setString(2, "row 2"); 46 pstmt.addBatch(); 47 48 pstmt.executeBatch(); 49 50 // 51 // 查询 输出结构集 52 // 53 rset = stmt.executeQuery("select * from mytest_table"); 54 while (rset.next()) 55 { 56 System.out.println(rset.getInt(1) +", "+ rset.getString(2)); 57 } 58 } 59 catch (Exception e) 60 { 61 e.printStackTrace(); 62 } 63 finally 64 { 65 if (stmt !=null) 66 { 67 try { stmt.execute("drop table mytest_table"); } catch (Exception e) {} 68 try { stmt.close(); } catch (Exception e) {} 69 } 70 if (pstmt !=null) 71 { 72 try { pstmt.close(); } catch (Exception e) {} 73 } 74 if (conn !=null) 75 { 76 try { conn.close(); } catch (Exception e) {} 77 } 78 } 79 } 80 } |
在MSSQLServer中呢,没有这个实用的特性吗,随后的几天自己开始注意了以下sql Server的架构,sql server号称是以C/S模式架构,其实它的前身Sybase DataServer 才是C/S模式关系型的第一款数据库。既然是C/S模式肯定就包含一个客户端与数据库段的交互过程,SQLServer在客户端使用一种称为TDS的协议来与服务器的Sqlserver服务器来进行数据库的交互,
TDS (Table Data Strem)
客户端使用称为表格格式数据流 (TDS) 的 SQL Server 专用应用程序级协议来发送 SQL 语句。SQL Server 2000 接受 TDS 的下列版本
SQL Server 2000 的 SQL Server 客户端组件版的客户端发送的 TDS 8.0
SQL Server 7.0 版的 SQL Server 客户端组件版的客户端发送的 TDS 7.0
SQL Server 6.5、6.0 和 4.21a 中运行 SQL Server 客户端组件的客户端所发送的 TDS 4.2
如图表示
客户段发送一条 select 之类的T-SQL语句,首先会进过TDS使用ODS(output data strem)来包装数据之后再发送到服务器端,在服务器端会有一个Net-librales的程序对各种网络协议进行监听,不管此时你使用的是tcp/ip还是什么其他的协议,Net-librales会根据连接近来的不同协议进行分类,然后归类集中监听、处理数据.。
当数据到达服务器端之后交由SQL引擎来处理,如下图所表示,
在 SQL Server 7.0 中,绝大多数来自客户机的功能调用都是通过 RPC(远程存贮过程控制) 消息进行的(但这不是本文想说明的重点),通常,作为 TDS SQL 语言消息的 SQL 语句直接在编译一端执行,再经过查询优化器进行一定的优化处理再将结果通过表达试服务返回给客户机,
在查询优化器中每编译(优化)一条T-SQL语句就会生成其对应的执行计划就是我们常说的缓存。但是平常在客户端提交上来的T-SQL 经过TDS的包装,即使2条T-SQL语句完全也不会生成完全相同的TDS格式的数据流,所以查询优化器编译之后会认为是2条不同的执行计划,所以每次都要去重新编译再缓存,浪费了不必要的时间。难道sqlserver真的做不到jdbc那样批量提交的优化功能吗?
其实在Sqlserver中有一个sp_executesql系统存储过程,通过使用它就能实现高效率的调用因为:
- 因为在 sp_executesql 中,Transact-SQL 语句的实际文本在两次执行之间未改变,所以查询优化器应该能将第二次执行中的 Transact-SQL 语句与第一次执行时生成的执行计划匹配。这样,SQL Server 不必编译第二条语句。
- Transact-SQL 字符串只生成一次。
整型参数按其本身格式指定。不需要转换为 Unicode。
比如
CREATETABLE May1998Sales
(OrderID INT PRIMARYKEY,
CustomerID INT NOTNULL,
OrderDate DATETIME NULL
CHECK (DATEPART(yy, OrderDate) =1998),
OrderMonth INT
CHECK (OrderMonth =5),
DeliveryDate DATETIME NULL,
CHECK (DATEPART(mm, OrderDate) = OrderMonth)
)
CREATEPROCEDURE InsertSales @PrmOrderIDINT, @PrmCustomerIDINT,
@PrmOrderDateDATETIME, @PrmDeliveryDateDATETIME
AS
DECLARE@InsertStringNVARCHAR(500)
DECLARE@OrderMonthINT
-- Build the INSERT statement.
SET@InsertString='INSERT INTO '+
/* Build the name of the table. */
SUBSTRING( DATENAME(mm, @PrmOrderDate), 1, 3) +
CAST(DATEPART(yy, @PrmOrderDate) ASCHAR(4) ) +
'Sales'+
/* Build a VALUES clause. */
' VALUES (@InsOrderID, @InsCustID, @InsOrdDate,'+
' @InsOrdMonth, @InsDelDate)'
/* Set the value to use for the order month because
functions are not allowed in the sp_executesql parameter
list. */
SET@OrderMonth=DATEPART(mm, @PrmOrderDate)
EXEC sp_executesql @InsertString,
N'@InsOrderID INT, @InsCustID INT, @InsOrdDate DATETIME,
@InsOrdMonth INT, @InsDelDate DATETIME',
@PrmOrderID, @PrmCustomerID, @PrmOrderDate,
@OrderMonth, @PrmDeliveryDate
GO
/*
在该过程中使用 sp_executesql 比使用 EXECUTE 执行字符串更有效。使用 sp_executesql 时,只生成 12 个版本的 INSERT 字符串,每个月的表 1 个。使用 EXECUTE 时,因为参数值不同,每个 INSERT 字符串均是唯一的。尽管两种方法生成的批处理数相同,但因为 sp_executesql 生成的 INSERT 字符串相似,所以查询优化程序更有可能反复使用执行计划
*/
呵呵

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

对于 SQL Server 数据库中已存在同名对象,需要采取以下步骤:确认对象类型(表、视图、存储过程)。如果对象为空,可使用 IF NOT EXISTS 跳过创建。如果对象有数据,使用不同名称或修改结构。使用 DROP 删除现有对象(谨慎操作,建议备份)。检查架构更改,确保没有引用删除或重命名的对象。

导入步骤如下:将 MDF 文件复制到 SQL Server 的数据目录(通常为 C:\Program Files\Microsoft SQL Server\MSSQL\DATA)。在 SQL Server Management Studio(SSMS)中,打开数据库并选择“附加”。单击“添加”按钮,选择 MDF 文件。确认数据库名称,点击确定按钮即可。

当 SQL Server 服务无法启动时,可采取以下步骤解决:检查错误日志以确定根本原因。确保服务帐户具有启动服务的权限。检查依赖项服务是否正在运行。禁用防病毒软件。修复 SQL Server 安装。如果修复不起作用,重新安装 SQL Server。

要查看 SQL Server 端口号:打开 SSMS,连接到服务器。在对象资源管理器中找到服务器名称,右键单击它,然后选择“属性”。在“连接”选项卡中,查看“TCP 端口”字段。

若误删 SQL Server 数据库,可采取以下步骤恢复:停止数据库活动;备份日志文件;检查数据库日志;恢复选项:从备份恢复;从事务日志恢复;使用 DBCC CHECKDB;使用第三方工具。请定期备份数据库并启用事务日志以防止数据丢失。

如果 SQL Server 安装失败,可通过以下步骤清理:卸载 SQL Server删除注册表项删除文件和文件夹重启计算机

SQL Server 英文安装可通过以下步骤更改为中文:下载相应语言包;停止 SQL Server 服务;安装语言包;更改实例语言;更改用户界面语言;重启应用程序。

可以通过以下步骤查询 SQL Server 数据库日志:1. 打开 SQL Server Management Studio,连接到数据库服务器;2. 展开“管理”节点,导航到“SQL Server 日志”;3. 选择要查询的日志文件,右键单击并选择“查看日志文件”;4. 浏览日志记录。其他查询日志方法:使用 Transact-SQL 查询、PowerShell Cmdlet。
