views:

241

answers:

3

Hello everyone,

I am using SQL Server 2008 and I need to select all data from one table of one DB into another table of another DB on the same SQL Server instance.

Here is my script using. The server will run out of memory. The data is big -- table is about 50G size on disk. Any easy alternative solution or any solution to lower memory consumption is fine. The server has 16G physical RAM and is x64.

Here is the statement I am using,

insert into [TargetDB].[dbo].[Orders]
select *
from [SourceDB].[dbo].[Orders];

Any quick and simple solutions?

thanks in advance, George

+2  A: 

Copy in batches

INSERT INTO [TargetDB].[dbo].[Orders]
SELECT TOP 100 *
FROM [SourceDB].[dbo].[Orders] S
WHERE NOT EXISTS
(
 SELECT 1 FROM [TargetDB].[dbo].[Orders] T1
 WHERE T1.OrderId = S.orderID
)

That should do it in batches of 100, which you could tweak to suit the number of records you need to process. This code does assume that you have some form of Unique value, such as OrderId to key off in the data copy process

Copy in ranges

If you have a field you can use to choose "ranges" such as an OrderDate, start off by running a query like

SELECT OrderDate, COUNT(1)
FROM [SourceDB].[dbo].[Orders]

to see how many distinct values there are and how many records there are per distinct value. That should allow you to choose some ranges (eg. 2009-01-01 -> 2009-01-31) and then use ranged queries to copy the data across:

INSERT INTO [TargetDB].[dbo].[Orders]
SELECT *
FROM [SourceDB].[dbo].[Orders] 
WHERE OrderDate BETWEEN '2009-01-01 00:00:00.000' AND '2009-01-31 23:59:59.997'
Rob
Thanks Rob, if I need to copy all the data to the destination database table, how to write a loop to let it complete all the things in some batches?
George2
@George2 - If it's a one off process, probably easier to do it in large chunks manually to give the database a chance to "breathe" between batches, particularly as you suffered out of memory problems previously =)
Rob
Hi Rob, in my table, there is no column which could be used as range indicator. I only have a GUID type ID which is used as clustered index. Any ideas for my solution? I do not need any concept of merge, the destination table is empty and I just need to copy all source data into the destination table. Thanks again!
George2
@George2 - use the first "copy in batches", scale the size of the "TOP" up to a coupla thousand or so, and run it until the data copy is complete
Rob
Thanks Rob, I think your idea of -- use the first "copy in batches", scale the size of the "TOP" up to a coupla thousand or so -- is really nice idea! But I do not know how to begin to write TSQL. Appreciate if you could provide me some code, then I can enrich?
George2
@George2 - use the code above (the first block of code), substituting the name of your Guid ID column for "OrderId" in the penultimate line and changing "TOP 100" in the second line to "TOP 2000", or however many you want. Then keep running the script until the "Rows Affected" is returned as ZERO :)
Rob
Possible to write in a loop?
George2
@George2 - yes, it's possible - but I refer you to my 2nd comment on this answer where I suggest doing it manually :)
Rob
+3  A: 

Add some partitioning so that you don't have so take it all at once. Get data for one month at a time, or all ID:s ending with a specific number.

That way each batch gets a bit smaller.

idstam
Thanks idstam, currently only ID is clustered primary key and it is of type GUID. I have an idea to write a loop and in each iteration copy a batch (e.g. 10,000 records for example for each iteration)?
George2
+1  A: 

You might want to look into using BCP to bulk copy the data.

Crappy Coding Guy