2008-08-26 138 views
16

最近,我開始改變一些我們的應用程序來支持MS SQL Server作爲替代後端。MS-SQL是否支持內存表?

我碰到的一個兼容性問題是使用MySQL的CREATE TEMPORARY TABLE來創建內存表,這些表保存數據以便在會話期間以非常快的速度訪問,而不需要永久存儲。

MS SQL中的等效項是什麼?

一個要求是我需要能夠像其他任何人一樣使用臨時表,尤其是JOIN它與永久的。

+1

我希望你知道在MySQL中,用戶創建的臨時表默認情況下不在內存中!只有在CREATE TABLE語句中指定ENGINE = MEMORY時,該表纔會在內存中。否則,臨時表將使用默認存儲引擎(很可能是MyISAM或INNODB)創建,並保存在磁盤上。 不要將用戶創建的內部臨時表與複雜連接期間由MySQL創建的臨時表混淆。如果可能的話,那些內存中創建。 – 2014-05-20 11:39:18

回答

13

@Keith

這是一種常見的誤解:表變量不一定存儲在存儲器中。實際上,SQL Server決定是將變量保存在內存中還是將其泄露到TempDB中。沒有可靠的方法(至少在SQL Server 2005中)來確保表數據保存在內存中。欲瞭解更詳細的信息外觀here

0

CREATE TABLE #tmptablename

使用哈希/英鎊符號前綴

3

可以在SQL Server 2005中申報了 「表變量」,像這樣:

declare @foo table (
    Id int, 
    Name varchar(100) 
); 

然後你參考它就像一個變量:

select * from @foo f 
    join bar b on b.Id = f.Id 

沒有必要放棄它 - 它消失時,日e變量超出範圍。

0

你想要的語法是:

創建表#tablename

#前綴標識表作爲臨時表。

1

與#和##與全球氣溫好的blog post here但基本上前綴本地臨時表 - 例如

CREATE TABLE #localtemp 
17

您可以創建表變量(在內存中),以及兩種不同類型的臨時表的:

--visible only to me, in memory (SQL 2000 and above only) 
declare @test table (
    Field1 int, 
    Field2 nvarchar(50) 
); 

--visible only to me, stored in tempDB 
create table #test (
    Field1 int, 
    Field2 nvarchar(50) 
) 

--visible to everyone, stored in tempDB 
create table ##test (
    Field1 int, 
    Field2 nvarchar(50) 
) 

編輯:

以下反饋我認爲這需要一點澄清。

#table##table將始終在TempDB中。

@Table變量通常在內存中,但不能保證是。 SQL根據查詢計劃決定,並在需要時使用TempDB。

1

我明白你想達到什麼。歡迎來到各種數據庫的世界!

SQL Server 2000支持通過在表名前添加#來創建臨時表,使其成爲本地可訪問的臨時表(對於本地會話)和前面的##表名,用於全局可訪問的臨時表,例如#MyLocalTable和## MyGlobalTable分別。

SQL Server 2005及以上版本支持兩種臨時表(本地和全球)和表變量 - 注意在表變量上的新功能在SQL 2008和發佈兩個!臨時表和表變量之間的區別不是很大,而在於數據庫服務器處理它們的方式。

我不希望談舊版本像7,6 SQL服務器的,雖然我已經與他們合作,它是我來自哪裏反正來了:-)

是很普遍認爲,表變量一直駐留在記憶中,但這是錯誤的。根據內存使用情況和事務的數據庫服務器量,可以從內存中導出表變量的頁面,並將其寫入tempdb中,其餘處理將在此處進行(在tempdb中)。

請注意,tempdb數據庫是與自然界中沒有永久對象實例的數據庫,但它負責處理涉及方交易物品分揀的工作量,和其他處理工作,這在本質上是暫時的。另一方面,表格變量(通常數據較小)保存在內存(RAM)中,使其訪問速度更快,因此在使用tempdb驅動器時,使用小型數據表變量與臨時表登錄tempdb。

表變量不能被索引而臨時表(本地和全局)的情況下可以編入索引的更快的處理的數據量是大的。所以,如果通過臨時事務處理更大的數據量,您就會知道您的選擇。還值得注意的是,單獨的表變量事務不會被記錄下來,並且無法回滾,而在臨時表上完成的事務可以回滾!

總之,對於較小的數據,表變量更好,而臨時表對於臨時處理的較大數據更好。如果您還希望使用事務塊進行正確的事務控制,則表變量不是回滾事務的選項,因此在這種情況下最好使用臨時表。

最後,臨時表會一直增加磁盤IO,因爲他們總是使用tempdb而表變量可能不會增加它,這取決於內存的壓力水平。

讓我知道,如果你想知道如何調整你的tempdb,以獲得更快的性能超過100%!

+0

克里斯,你爲什麼不建立一個SO賬戶? – 2009-09-09 15:44:33

2

有可能與MS SQL服務器2014年

參見:http://msdn.microsoft.com/en-us/library/dn133079.aspx

這裏是SQL生成代碼(從MSDN)的例子:

-- create a database with a memory-optimized filegroup and a container. 
CREATE DATABASE imoltp 
GO 

ALTER DATABASE imoltp ADD FILEGROUP imoltp_mod CONTAINS MEMORY_OPTIMIZED_DATA 
ALTER DATABASE imoltp ADD FILE (name='imoltp_mod1', filename='c:\data\imoltp_mod1') TO FILEGROUP imoltp_mod 
ALTER DATABASE imoltp SET MEMORY_OPTIMIZED_ELEVATE_TO_SNAPSHOT=ON 
GO 

USE imoltp 
GO 


-- create a durable (data will be persisted) memory-optimized table 
-- two of the columns are indexed 
CREATE TABLE dbo.ShoppingCart ( 
    ShoppingCartId INT IDENTITY(1,1) PRIMARY KEY NONCLUSTERED, 
    UserId INT NOT NULL INDEX ix_UserId NONCLUSTERED HASH WITH (BUCKET_COUNT=1000000), 
    CreatedDate DATETIME2 NOT NULL, 
    TotalPrice MONEY 
) WITH (MEMORY_OPTIMIZED=ON) 
GO 

-- create a non-durable table. Data will not be persisted, data loss if the server turns off unexpectedly 
CREATE TABLE dbo.UserSession ( 
    SessionId INT IDENTITY(1,1) PRIMARY KEY NONCLUSTERED HASH WITH (BUCKET_COUNT=400000), 
    UserId int NOT NULL, 
    CreatedDate DATETIME2 NOT NULL, 
    ShoppingCartId INT, 
    INDEX ix_UserId NONCLUSTERED HASH (UserId) WITH (BUCKET_COUNT=400000) 
) WITH (MEMORY_OPTIMIZED=ON, DURABILITY=SCHEMA_ONLY) 
GO