【问题标题】:Select into memory optimised table选择到内存优化表
【发布时间】:2017-02-28 09:47:57
【问题描述】:

我有一个存储过程,可以根据数据库设置将一些动态 sql 转换为临时表或视图。这用于根据数据大小在不同客户端之间“调整”数据库功能,即临时表创建时间较长但设置时间较长,视图创建速度快但读取时间稍长。

我正在考虑将其扩展为包含内存优化表的选项,但如果不先完全声明它,我看不到如何使用内存优化表。

我现在的代码格式如下:

SELECT TOP 10 *
INTO FavoriteCustomers
FROM Customers
ORDER BY Spend DESC

如您所见,我没有声明表格,只是使用 select into。有什么办法可以选择内存优化表?我可以使用:

sys.dm_exec_describe_first_result_set(@mySQLhere)

这为我传入的 TSQL 提供了一个列定义。然后使用此信息预先构建表并插入其中,但如果可能的话,我希望有一个更简洁的方法。

有人有解决办法吗?搜索只是让我了解如何将数据添加到 MOT 而不是 MOT 创建作为选择的一部分。

我知道这可能是不可能的,并且我确实有描述的解决方法,我只是觉得我可能在这里错过了更好的选择。

目前使用多台服务器,MOT功能只在SQL2016上实现。

非常感谢。

【问题讨论】:

  • 我正在研究类似的方法,尝试强制以特定顺序执行查询而不损失性能。我想他们会在这篇文章中提到这样一个解决方案,如果它存在的话,用内存优化表替换临时表:docs.microsoft.com/en-us/sql/relational-databases/…
  • 我从来没有找到一个很好的解决方法。我最终首先创建了表,然后使用标准插入查询。它工作正常。我将发布我的代码作为答案。

标签: sql sql-server dynamic-sql sql-server-2016 memory-optimized-tables


【解决方案1】:
CREATE PROC [engine].[usp_CreateDynamicContent]
    @ContentName AS NVARCHAR(MAX)
,   @NTS_SessionID NVARCHAR(MAX)
,   @SelectSQL NVARCHAR(MAX)
,   @PrimaryKeyField NVARCHAR(MAX) = NULL
,   @NonClusteredIndexField NVARCHAR(MAX) = NULL
,   @debug BIT = 0
AS
    BEGIN

        DECLARE @ContentType AS NVARCHAR(MAX)
        DECLARE @dcName AS NVARCHAR(MAX)
        DECLARE @strSQL AS NVARCHAR(MAX)

        SET @dcName = 'tmp.dc_' + @ContentName + '_' + @NTS_SessionID

        IF OBJECT_ID(@dcName, 'V') IS NOT NULL /* Drop the view if it exists */
            BEGIN
                SET @strSQL = 'DROP VIEW ' + @dcName
                IF @debug = 1
                    PRINT (@strSQL)
                EXEC (@strSQL)
            END

        IF OBJECT_ID(@dcName) IS NOT NULL /* Drop the table if it exists */
            BEGIN
                SET @strSQL = 'DROP TABLE ' + @dcName
                IF @debug = 1
                    PRINT (@strSQL)
                EXEC (@strSQL)
            END

        /* This is my database listing types for each table. */
        SELECT  @ContentType = ContentType
        FROM    guid.DynamicContents
        WHERE   ContentName = @ContentName

        IF @ContentType = 'VIEW'
            BEGIN
                SET @strSQL = 'CREATE VIEW ' + @dcName + ' AS' + CHAR(13) + @SelectSQL
                IF @debug = 1
                    PRINT (@strSQL)
                EXEC (@strSQL)
            END
        ELSE
            IF @ContentType IN ('TABLE', 'MOT')
                BEGIN
                    SET @strSQL = ''
                    SELECT  @strSQL = @strSQL + ',' + CHAR(10) + '[' + name + '] ' + system_type_name + CASE WHEN @PrimaryKeyField IS NOT NULL
                                                                                                                  AND @ContentType = 'MOT' THEN ' NOT NULL PRIMARY KEY NONCLUSTERED'
                                                                                                             ELSE ''
                                                                                                        END + CHAR(13)
                    FROM    sys.dm_exec_describe_first_result_set(@SelectSQL, NULL, 0)
                    SET @strSQL = STUFF(@strSQL, 1, 1, 'CREATE TABLE ' + @dcName + '(')

                    IF @PrimaryKeyField IS NOT NULL
                        AND @ContentType = 'TABLE'
                        BEGIN
                            SET @strSQL = @strSQL + CHAR(10) + ',CONSTRAINT pk_' + @ContentName + '_' + @NTS_SessionID + ' PRIMARY KEY (' + @PrimaryKeyField + ')' + CHAR(10)
                        END

                    SET @strSQL = @strSQL + ')'
                    IF @debug = 1
                        PRINT (@strSQL)
                    EXEC (@strSQL)

                    IF @NonClusteredIndexField IS NOT NULL
                        AND @ContentType = 'TABLE'
                        BEGIN
                            SET @strSQL = 'CREATE NONCLUSTERED INDEX ix_' + @ContentName + '_' + @NonClusteredIndexField + ' ON ' + @dcName + ' (' + @NonClusteredIndexField + ')'
                            IF @debug = 1
                                PRINT (@strSQL)
                            EXEC (@strSQL)
                        END

                    /* This section added in as I use cte's quite a lot */
                    IF @SelectSQL LIKE '%/* INSERT HERE */%'
                        BEGIN
                            SET @strSQL = REPLACE(@SelectSQL, '/* INSERT HERE */', 'INSERT INTO ' + @dcName)
                        END
                    ELSE
                        BEGIN
                            SET @strSQL = 'INSERT INTO ' + @dcName + CHAR(13) + @SelectSQL 
                        END
                    IF @debug = 1
                        PRINT (@strSQL)
                    EXEC (@strSQL)
                END

    END

【讨论】:

  • 请补充说明
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-01
  • 1970-01-01
相关资源
最近更新 更多