MS-SQL 是否支持内存表?
-
09-06-2019 - |
题
最近,我开始更改我们的一些应用程序以支持 MS SQL Server
作为替代后端。
我遇到的兼容性问题之一是使用 MySQL 的 CREATE TEMPORARY TABLE 创建内存表,该表保存数据以便在会话期间非常快速地访问,而不需要永久存储。
MS SQL 中的等效项是什么?
一个要求是我需要能够像使用其他表一样使用临时表,尤其是 JOIN
它与永久的。
解决方案
@基思
这是一个普遍的误解:表变量不一定存储在内存中。事实上,SQL Server 决定是将变量保留在内存中还是将其溢出到 TempDB。没有可靠的方法(至少在 SQL Server 2005 中)确保表数据保存在内存中。更详细的信息请看 这里
其他提示
您可以创建表变量(在内存中)和两种不同类型的临时表:
--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。
您可以在 SQL Server 2005 中声明“表变量”,如下所示:
declare @foo table (
Id int,
Name varchar(100)
);
然后您就像引用变量一样引用它:
select * from @foo f
join bar b on b.Id = f.Id
无需删除它 - 当变量超出范围时它就会消失。
MS SQL Server 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
一个好的 博客文章在这里 但基本上本地临时表前缀为#,全局临时表前缀为## - 例如
CREATE TABLE #localtemp
我理解你想要实现的目标。欢迎来到各种数据库的世界!
SQL Server 2000 支持通过在表名前添加 # 前缀来创建临时表,使其成为本地可访问的临时表(会话本地),并在表名前添加 ##,以实现全局可访问的临时表,例如 #MyLocalTable 和 ##MyGlobalTable分别。
SQL Server 2005 及更高版本支持临时表(本地、全局)和表变量 - 请注意 SQL 2008 和第二版中表变量的新功能!临时表和表变量之间的区别并不是很大,而是在于数据库服务器处理它们的方式。
我不想谈论旧版本的 SQL Server,例如 7、6,尽管我曾经使用过它们,而且无论如何,它们就是我的出处:-)
人们通常认为表变量总是驻留在内存中,但这是错误的。根据内存使用情况和数据库服务器事务量,表变量的页面可能会从内存中导出并写入到 tempdb 中,其余处理则在那里进行(在 tempdb 中)。
请注意,tempdb 是实例上的数据库,本质上没有永久对象,但它负责处理涉及排序等辅助事务的工作负载以及其他本质上是临时的处理工作。另一方面,表变量(通常具有较小的数据)保存在内存 (RAM) 中,从而使它们的访问速度更快,因此与临时表相比,使用具有较小数据的表变量时,使用 tempdb 驱动器时的磁盘 IO 更少登录临时数据库。
表变量无法建立索引,而临时表(本地和全局)可以建立索引,以便在数据量较大时加快处理速度。因此,您知道如何选择通过临时事务更快地处理更大数据量的情况。还值得注意的是,仅对表变量进行的事务不会被记录,并且无法回滚,而对临时表进行的事务则可以回滚!
总之,表变量更适合较小的数据,而临时表更适合临时处理的较大数据。如果您还希望使用事务块进行适当的事务控制,则表变量不是回滚事务的选项,因此在这种情况下最好使用临时表。
最后,临时表总是会增加磁盘 IO,因为它们始终使用 tempdb,而表变量可能不会增加磁盘 IO,具体取决于内存压力级别。
如果您需要有关如何调整 tempdb 以获得更快性能以超过 100% 的提示,请告诉我!
您想要的语法是:
创建表#表名
# 前缀将该表标识为临时表。
创建表#tmptablename
使用井号/井号前缀