通过链接服务器将实例A上的数据写入实例B,通常有以下两种方式
--方案1:在实例A上执行
insert into LinkForB.B..TableB select * from TableA
--方案2:在实例B上执行
insert into TableB select * from LinkForA.A..TableA
目前接手的数据库,大量使用链接服务器来搬迁数据,并且使用者随心所欲。本地写入到链接服务器,从链接服务器读数据写入本地,从链接服务器读数据写入到另一链接服务器。更有坑爹的,本来是写入本地,却在本地的前面加上本地实例的链接服务器!

--20160519
问个问题,实例A上的作业通过链接服务器从实例B获取数据然后写入到实例C,三个实例在不同的服务器。这个实例A充当的是什么角色,它和直接实例B"推"数据给实例C,或者实例C从实例B"拉"数据有什么区别,优劣势如何?
--20160629
Q:三台数据库服务器A、B、C,大致的定位是A写入、B读取、C归档。所有新数据写入到A;页面查询、统计作业放在B。目前A到B,B到C是在作业中通过链接服务器insert...select from linksvr的方式。然后会定期删除A、B中的历史数据。感觉这种方式不稳定,而且如果表的个数很多,通过链接服务器也不方便。大家有没有什么建议?
A:1、使用复制,A复制到B和C;2、AlwaysOn;3、定时跑存储过程,将要插入的语句和删除的语句放在存储过程里面。你把插入的语句放在它本机,通过链接服务器去查询。

以前没有特别关注哪种方式更好,有在群里针对搬迁数据的方式请教过,有朋友建议最好采用pull的链接方式,即insert into TableB select * from LinkForA.A..TableA
偶然看到园子里的文章(为什么透过链接服务器写入,速度会很慢),结合自己遇到的问题,尝试分析通过链接服务器insert数据的区别。
此处为了方便,我所创建的链接服务器[MY]实际是指向当前实例,但是不影响对结果的分析。
首先创建测试表,并在测试表上创建触发器

USE TEST
GO
--脚本参考http://www.cnblogs.com/wanyong117/p/5764644.html修改
--创建测试表
CREATE TABLE [dbo].[Product](
[ProductID] INT,
[Name] [nvarchar](50),
[Remark] [nvarchar](50)
)
GO
--创建触发器
CREATE TRIGGER [dbo].[Product_TR]
ON [dbo]. [Product]
FOR INSERT
AS
BEGIN
SET XACT_ABORT ON
BEGIN TRY
IF (select len(ProductID) from inserted)>0--当select查询只返回一个值时才能操作=、!=、<、<=、>、>=
BEGIN
PRINT 'one row'
END
END TRY
BEGIN CATCH
PRINT '消息 '+CONVERT(VARCHAR,ERROR_NUMBER())+',级别 '+CONVERT(VARCHAR,ERROR_SEVERITY())
+',状态 '+CONVERT(VARCHAR,ERROR_STATE())+',过程 '+CONVERT(VARCHAR,ERROR_PROCEDURE())
+',第 '+CONVERT(VARCHAR,ERROR_LINE())+' 行'
PRINT ERROR_MESSAGE()
END CATCH
END
GO

注意触发器脚本,是为了在批量插入数据,select...from inserted子查询返回多条记录,进行>操作出错。
插入数据检验

--Step1:插入1条数据,成功
INSERT [Test].[dbo].[Product]( [ProductID],[Name],[Remark])
SELECT TOP 1 [ProductID],[Name],'one row'
FROM [AdventureWorks2008R2].[Production].[Product]
--Step2:插入5条数据,失败
INSERT [Test].[dbo].[Product]( [ProductID],[Name],[Remark])
SELECT TOP 5 [ProductID],[Name],'more than one row'
FROM [AdventureWorks2008R2].[Production].[Product]
--Step3:插入5条数据到链接服务器,成功
INSERT [MY].[Test].[dbo].[Product]([ProductID],[Name],[Remark])
SELECT TOP 5 [ProductID],[Name],'ToLink more than one row'
FROM [AdventureWorks2008R2].[Production].[Product]
--Step4:从链接服务器获取5条数据再插入,失败
INSERT [Test].[dbo].[Product]( [ProductID],[Name],[Remark])
SELECT TOP 5 [ProductID],[Name],'FromLink more than one row'
FROM [MY].[AdventureWorks2008R2].[Production].[Product]

Step2和Step4的错误信息如下

我们查看表中数据

通过图中的Remark字段,可以看出Step1和Step3的语句执行成功,Step2和Step4的语句执行失败
Step1:插入1条数据时,select...from inserted子查询返回1行值,它可和0进行比较(>),数据insert成功。
Step2:插入5条数据时,select...from inserted子查询返回5行值,它不能和单一的0进行比较,触发器报错,整个insert语句失败。
Step3:插入5条数据到链接服务器,竟然成功!对比前面的语句,说明insert into linksvr.db.sch.tb是一行一行的insert(因为表上有触发器,如果一次多行insert会报错)
Step4:当从链接服务器获取5条数据,再insert失败!它近似等效于Step2。
现在我们的问题是Step3和Step4到底哪个更高效?虽然此时我们已经知道,Step3会拆分成单条写入,Step4一次写入多条。为了让这两个语句正常执行,我们禁用表上的触发器

--禁用/启用触发器
alter table [dbo].[Product]
disable trigger [Product_TR] --disable/enable
--查看触发器
select name,type_desc,create_date,modify_date,is_disabled from sys.triggers t


开启跟踪,然后再次执行Step3、Step4中的语句

INSERT [MY].[Test].[dbo].[Product]([ProductID],[Name],[Remark])
SELECT TOP 5 [ProductID],[Name],'ToLink more than one row'
FROM [AdventureWorks2008R2].[Production].[Product]


在SPID=52窗口执行INSERT Linksvr SELECT TOP 5 FROM语句,链接服务器在SPID=55下执行,有5个RPC:Completed事件

INSERT [Test].[dbo].[Product]( [ProductID],[Name],[Remark])
SELECT TOP 5 [ProductID],[Name],'FromLink more than one row'
FROM [MY].[AdventureWorks2008R2].[Production].[Product]


在SPID=52窗口执行INSERT Tab SELECT TOP 5 FROM Linksvr语句,链接服务器在SPID=55的会话中执行,仅一个RPC:Completed事件
此时表中的数据如下

如果将表中数据全部写入到测试表,跟踪添加筛选器SPID=52

Duration字段可以看出insert linksvr要比insert select linksvr耗时些。其实就是要存一万块钱,是每次只存一百(需100次),还是每次存一万(需1次)。显然后者更高效。

--删除测试表
USE TEST
GO
DROP TABLE [TEST].[dbo].[Product]

insert into linksvr or insert into from linksvr的更多相关文章

  1. 使用batch insert解决MySQL的insert吞吐量问题

    最近使用了一个非常简单易用的方法解决了业务上的一个insert吞吐量的问题,在此总结一下. 首先我们明确一下,insert吞吐量其实并不是指的IPS(insert per second),而是指的RP ...

  2. mysql 数据库插入语句之insert into,replace into ,insert ignore

    近期才发现mysql的插入语句竟然有如此多的使用方法,这里拿来分享一下. ①关于insert into : insert into table_name values(); insert into t ...

  3. Sqlite执行insert or ignore 或insert or replace语句。

    Sqlite执行insert or ignore 或insert or replace语句. ,); ,); 上面的第一条语句是每次执行时,如果不存在,则添加,如果存在,则更新. 上面的第二条语句是每 ...

  4. Hive:insert into table 与 insert overwrite table 区别

    创建测试表,来测试看看测试结果: create table test(name string,pwd string,createdate string)row format delimited fie ...

  5. sqlite "insert or replace" 和 "insert or ignore" 用法

    insert or replace:如果不存在就插入,存在就更新insert or ignore:如果不存在就插入,存在就忽略只对UNIQUE约束的字段起作用.举例:建表:CREATE TABLE T ...

  6. oracle 中 insert select 和 select insert 配合使用

    Insert Into select 与 Select Into 哪个更快? 在平常数据库操作的时候,我们有时候会遇到表之间数据复制的情况,可能会用到INSERT INTO SELECT 或者 SEL ...

  7. SQL Server 动态生成数据库所有表Insert语句

    一. 背景 SQL Server,如果我们需要把数据库A的所有表数据到数据库B中,通常我们会怎么做呢?我会使用SSMS的导入导出功能,进行表数据的导入导出,无可厚非,这样的导入非常简单和方便: 但是, ...

  8. MyBatis魔法堂:Insert操作详解(返回主键、批量插入)

    一.前言    数据库操作怎能少了INSERT操作呢?下面记录MyBatis关于INSERT操作的笔记,以便日后查阅. 二. insert元素 属性详解   其属性如下: parameterType  ...

  9. oracle中 SELECT INTO 和INSERT INTO ... SELECT区别

    在Oracle中,将一张表的数据复制到另外一个对象中.通常会有这两种方法:insert into select  和 select into from. 前者可以将select 出来的N行(0到任意数 ...

随机推荐

  1. 【Java EE 学习 33 上】【JQuery样式操作】【JQuery中的Ajax操作】【JQuery中的XML操作】

    一.JQuery中样式的操作 1.给id=mover的div采用属性增加样式.one $("#b1").click(function(){ $("#mover" ...

  2. 带callback的future实现

    jdk暂时不支持,所以只有自己实现带callback的future. 完成后callback的 final TaskPromise promise = new DefaultTaskPromise() ...

  3. 第二十八篇:SOUI中自定义控件开发过程

    在SOUI中已经提供了大部分常用的控件,但是内置控件不可能满足用户的所有要求,因此一个真实的应用少不得还要做一些自定义控件. 学习一个新东西,最简单的办法就是依葫芦画瓢.事实上在SOUI系统中内置控件 ...

  4. Python 元组

    #不可变序列-----元组 tuple #元组和列表十分相似,元组和字符串一样都是不可变的. #元组由不同的元素组成,每个元素可以存储不同类型的数据,例如 #字符串.数字和元组 #元组通常代表一行数据 ...

  5. Hibernate关联关系的映射

    实体之间的关系 实体之间有三种关系 一对多:一个用户,生成多个订单,每一个订单只能属于一个用户 建表原则:在多的一方创建一个字段,作为外键,指向一的一方的主键 多对多:一个学生可以选择多门课程,一个课 ...

  6. 归一化交叉相关Normalization cross correlation (NCC)

    归一化交叉相关Normalization cross correlation (NCC) 相关系数,图像匹配 NCC正如其名字,是用来描述两个目标的相关程度的,也就是说可以用来刻画目标间的相似性.一般 ...

  7. Why do we live in this world?

    Why do we live in this world? It seems to me there is nothing but two reasons, - to live the livabil ...

  8. MySQL查询语句(select)详解(1)

    1.查询记录 select*from 表名 [where 条件];eg:select*from students;//查询 students 表中所有记录,所有字段的值都显示出来select fiel ...

  9. Vue.js组件之联动下拉框

    Html代码 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UT ...

  10. C语言中定义全局变量

    (1)在C语言的头文件中定义变量出现的问题 最好不要傻嘻嘻的在头文件里定义什么东西.比如全局变量: /*xx头文件*/ #ifndef  _XX_头文件.H #define  _XX_头文件.H in ...