logical reads on global temp table, but not on session-level temp table Announcing the arrival of Valued Associate #679: Cesar Manara Planned maintenance scheduled April 17/18, 2019 at 00:00UTC (8:00pm US/Eastern)Get minimal logging when loading data into temporary tablesCheck existence with EXISTS outperform COUNT! … Not?Which of these queries is best for performance?SQL Server - Logical Reads lowered, Execution time remained the sameMulti-statement TVF vs Inline TVF PerformanceLogical reads different when accessing the same LOB dataOPTION (RECOMPILE) is Always Faster; Why?Does IMAGE column affect query performance even if it's not included in the query?Helpful nonclustered index improved the query but raised logical readsAggregation in Outer Apply vs Left Join vs Derived tableHigh processor utilization when running a stored procedure

How to motivate offshore teams and trust them to deliver?

Should I discuss the type of campaign with my players?

List *all* the tuples!

Why does Python start at index -1 when indexing a list from the end?

Is there a concise way to say "all of the X, one of each"?

What do you call a phrase that's not an idiom yet?

How can I fade player character when he goes inside or outside of the area?

Do I really need recursive chmod to restrict access to a folder?

Is the address of a local variable a constexpr?

What is the musical term for a note that continously plays through a melody?

How to bypass password on Windows XP account?

iPhone Wallpaper?

Why don't the Weasley twins use magic outside of school if the Trace can only find the location of spells cast?

Proof involving the spectral radius and the Jordan canonical form

Withdrew £2800, but only £2000 shows as withdrawn on online banking; what are my obligations?

Single word antonym of "flightless"

What would be the ideal power source for a cybernetic eye?

Check which numbers satisfy the condition [A*B*C = A! + B! + C!]

How to deal with a team lead who never gives me credit?

Is 1 ppb equal to 1 μg/kg?

When to stop saving and start investing?

Sorting numerically

Why constant symbols in a language?

Did Kevin spill real chili?



logical reads on global temp table, but not on session-level temp table



Announcing the arrival of Valued Associate #679: Cesar Manara
Planned maintenance scheduled April 17/18, 2019 at 00:00UTC (8:00pm US/Eastern)Get minimal logging when loading data into temporary tablesCheck existence with EXISTS outperform COUNT! … Not?Which of these queries is best for performance?SQL Server - Logical Reads lowered, Execution time remained the sameMulti-statement TVF vs Inline TVF PerformanceLogical reads different when accessing the same LOB dataOPTION (RECOMPILE) is Always Faster; Why?Does IMAGE column affect query performance even if it's not included in the query?Helpful nonclustered index improved the query but raised logical readsAggregation in Outer Apply vs Left Join vs Derived tableHigh processor utilization when running a stored procedure



.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








10















Consider the following simple MCVE:



SET STATISTICS IO, TIME OFF;
USE tempdb;

IF OBJECT_ID(N'tempdb..#t1', N'U') IS NOT NULL DROP TABLE #t1;
CREATE TABLE #t1
(
r int NOT NULL
);

IF OBJECT_ID(N'tempdb..##t1', N'U') IS NOT NULL DROP TABLE ##t1;
CREATE TABLE ##t1
(
r int NOT NULL
);

IF OBJECT_ID(N'dbo.s1', N'U') IS NOT NULL DROP TABLE dbo.s1;
CREATE TABLE dbo.s1
(
r int NOT NULL
PRIMARY KEY CLUSTERED
);

INSERT INTO dbo.s1 (r)
SELECT TOP(10000) ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM sys.syscolumns sc1
CROSS JOIN sys.syscolumns sc2;
GO


When I run the following inserts, inserting into #t1 shows no stats I/O for the temp table. However, inserting into ##t1 does show stats I/O for the temp table.



SET STATISTICS IO, TIME ON;
GO

INSERT INTO #t1 (r)
SELECT r
FROM dbo.s1;


The stats output:



SQL Server parse and compile time: 
CPU time = 0 ms, elapsed time = 1 ms.
Table 's1'. Scan count 1, logical reads 19, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

SQL Server Execution Times:
CPU time = 16 ms, elapsed time = 9 ms.

(10000 rows affected)


INSERT INTO ##t1 (r)
SELECT r
FROM dbo.s1;


SQL Server parse and compile time: 
CPU time = 0 ms, elapsed time = 1 ms.
Table '##t1'. Scan count 0, logical reads 10016, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 's1'. Scan count 1, logical reads 19, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

SQL Server Execution Times:
CPU time = 47 ms, elapsed time = 45 ms.

(10000 rows affected)


Why are there so many reads on the ##temp table when I'm only inserting into it?










share|improve this question




























    10















    Consider the following simple MCVE:



    SET STATISTICS IO, TIME OFF;
    USE tempdb;

    IF OBJECT_ID(N'tempdb..#t1', N'U') IS NOT NULL DROP TABLE #t1;
    CREATE TABLE #t1
    (
    r int NOT NULL
    );

    IF OBJECT_ID(N'tempdb..##t1', N'U') IS NOT NULL DROP TABLE ##t1;
    CREATE TABLE ##t1
    (
    r int NOT NULL
    );

    IF OBJECT_ID(N'dbo.s1', N'U') IS NOT NULL DROP TABLE dbo.s1;
    CREATE TABLE dbo.s1
    (
    r int NOT NULL
    PRIMARY KEY CLUSTERED
    );

    INSERT INTO dbo.s1 (r)
    SELECT TOP(10000) ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
    FROM sys.syscolumns sc1
    CROSS JOIN sys.syscolumns sc2;
    GO


    When I run the following inserts, inserting into #t1 shows no stats I/O for the temp table. However, inserting into ##t1 does show stats I/O for the temp table.



    SET STATISTICS IO, TIME ON;
    GO

    INSERT INTO #t1 (r)
    SELECT r
    FROM dbo.s1;


    The stats output:



    SQL Server parse and compile time: 
    CPU time = 0 ms, elapsed time = 1 ms.
    Table 's1'. Scan count 1, logical reads 19, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

    SQL Server Execution Times:
    CPU time = 16 ms, elapsed time = 9 ms.

    (10000 rows affected)


    INSERT INTO ##t1 (r)
    SELECT r
    FROM dbo.s1;


    SQL Server parse and compile time: 
    CPU time = 0 ms, elapsed time = 1 ms.
    Table '##t1'. Scan count 0, logical reads 10016, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    Table 's1'. Scan count 1, logical reads 19, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

    SQL Server Execution Times:
    CPU time = 47 ms, elapsed time = 45 ms.

    (10000 rows affected)


    Why are there so many reads on the ##temp table when I'm only inserting into it?










    share|improve this question
























      10












      10








      10


      1






      Consider the following simple MCVE:



      SET STATISTICS IO, TIME OFF;
      USE tempdb;

      IF OBJECT_ID(N'tempdb..#t1', N'U') IS NOT NULL DROP TABLE #t1;
      CREATE TABLE #t1
      (
      r int NOT NULL
      );

      IF OBJECT_ID(N'tempdb..##t1', N'U') IS NOT NULL DROP TABLE ##t1;
      CREATE TABLE ##t1
      (
      r int NOT NULL
      );

      IF OBJECT_ID(N'dbo.s1', N'U') IS NOT NULL DROP TABLE dbo.s1;
      CREATE TABLE dbo.s1
      (
      r int NOT NULL
      PRIMARY KEY CLUSTERED
      );

      INSERT INTO dbo.s1 (r)
      SELECT TOP(10000) ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
      FROM sys.syscolumns sc1
      CROSS JOIN sys.syscolumns sc2;
      GO


      When I run the following inserts, inserting into #t1 shows no stats I/O for the temp table. However, inserting into ##t1 does show stats I/O for the temp table.



      SET STATISTICS IO, TIME ON;
      GO

      INSERT INTO #t1 (r)
      SELECT r
      FROM dbo.s1;


      The stats output:



      SQL Server parse and compile time: 
      CPU time = 0 ms, elapsed time = 1 ms.
      Table 's1'. Scan count 1, logical reads 19, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

      SQL Server Execution Times:
      CPU time = 16 ms, elapsed time = 9 ms.

      (10000 rows affected)


      INSERT INTO ##t1 (r)
      SELECT r
      FROM dbo.s1;


      SQL Server parse and compile time: 
      CPU time = 0 ms, elapsed time = 1 ms.
      Table '##t1'. Scan count 0, logical reads 10016, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
      Table 's1'. Scan count 1, logical reads 19, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

      SQL Server Execution Times:
      CPU time = 47 ms, elapsed time = 45 ms.

      (10000 rows affected)


      Why are there so many reads on the ##temp table when I'm only inserting into it?










      share|improve this question














      Consider the following simple MCVE:



      SET STATISTICS IO, TIME OFF;
      USE tempdb;

      IF OBJECT_ID(N'tempdb..#t1', N'U') IS NOT NULL DROP TABLE #t1;
      CREATE TABLE #t1
      (
      r int NOT NULL
      );

      IF OBJECT_ID(N'tempdb..##t1', N'U') IS NOT NULL DROP TABLE ##t1;
      CREATE TABLE ##t1
      (
      r int NOT NULL
      );

      IF OBJECT_ID(N'dbo.s1', N'U') IS NOT NULL DROP TABLE dbo.s1;
      CREATE TABLE dbo.s1
      (
      r int NOT NULL
      PRIMARY KEY CLUSTERED
      );

      INSERT INTO dbo.s1 (r)
      SELECT TOP(10000) ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
      FROM sys.syscolumns sc1
      CROSS JOIN sys.syscolumns sc2;
      GO


      When I run the following inserts, inserting into #t1 shows no stats I/O for the temp table. However, inserting into ##t1 does show stats I/O for the temp table.



      SET STATISTICS IO, TIME ON;
      GO

      INSERT INTO #t1 (r)
      SELECT r
      FROM dbo.s1;


      The stats output:



      SQL Server parse and compile time: 
      CPU time = 0 ms, elapsed time = 1 ms.
      Table 's1'. Scan count 1, logical reads 19, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

      SQL Server Execution Times:
      CPU time = 16 ms, elapsed time = 9 ms.

      (10000 rows affected)


      INSERT INTO ##t1 (r)
      SELECT r
      FROM dbo.s1;


      SQL Server parse and compile time: 
      CPU time = 0 ms, elapsed time = 1 ms.
      Table '##t1'. Scan count 0, logical reads 10016, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
      Table 's1'. Scan count 1, logical reads 19, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

      SQL Server Execution Times:
      CPU time = 47 ms, elapsed time = 45 ms.

      (10000 rows affected)


      Why are there so many reads on the ##temp table when I'm only inserting into it?







      sql-server sql-server-2016 temporary-tables






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Apr 1 at 21:06









      Max VernonMax Vernon

      52.4k13115232




      52.4k13115232




















          1 Answer
          1






          active

          oldest

          votes


















          9














          Minimal logging is not being used when using INSERT INTO and global temp tables



          Inserting one million rows in a global temp table by using INSERT INTO



          INSERT INTO ##t1 (r)
          SELECT top(1000000) s1.r
          FROM dbo.s1
          CROSS APPLY dbo.s1 S2;


          When running SELECT * FROM fn_dblog(NULL, NULL) while the above query is executing, ~1M rows are returned.



          enter image description here



          One LOP_INSERT_ROW operation for each row + other
          log data.




          The same insert on a local temp table



          INSERT INTO #t1 (r)
          SELECT top(1000000) s1.r
          FROM dbo.s1
          CROSS APPLY dbo.s1 S2;


          Only going up to 700 rows returned by SELECT * FROM fn_dblog(NULL, NULL)



          enter image description here



          Minimal logging




          Inserting one million rows in a global temp table by using SELECT INTO



          SELECT top(1000000) s1.r
          INTO ##t2
          FROM dbo.s1
          CROSS APPLY dbo.s1 S2;


          enter image description here



          SELECT INTO a global temp table with 10k records



          SELECT s1.r
          INTO ##t2
          FROM dbo.s1;


          Time and IO Statistics



          SQL Server parse and compile time: 
          CPU time = 0 ms, elapsed time = 0 ms.
          Table 's1'. Scan count 1, logical reads 19, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

          SQL Server Execution Times:
          CPU time = 16 ms, elapsed time = 10 ms.
          SQL Server parse and compile time:
          CPU time = 0 ms, elapsed time = 0 ms.



          Based on this blogpost we can add TABLOCK to initiate minimal logging on a heap table



          INSERT INTO ##t1 WITH(TABLOCK) (r)
          SELECT s1.r
          FROM dbo.s1


          Low logical reads



          Table 's1'. Scan count 1, logical reads 19, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

          (10000 rows affected)



          Part of an answer by @PaulWhite on how to achieve minimal logging on temporary tables




          No. Local temporary tables (#temp) are private to the creating
          session, so a table lock hint is not required. A table lock hint would
          be required for a global temporary table (##temp) or a regular table
          (dbo.temp) created in tempdb, because these can be accessed from
          multiple sessions.




          Creating a regular table to test this:



          CREATE TABLE dbo.bla
          (
          r int NOT NULL
          );


          Filling it up with 1M records



          INSERT INTO bla 
          SELECT top(1000000)s1.r
          FROM dbo.s1
          CROSS APPLY dbo.s1 S2;


          >1M logical reads on this table



          Table 's1'. Scan count 17, logical reads 155, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
          Table 'bla'. Scan count 0, logical reads 1001607, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
          Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.



          Paul White's answer explaining the logical reads reported on the global temp table




          Generally, logical reads are reported for the target table when the
          insert is not minimally logged.



          These logical reads are associated with finding a place in the
          existing structure to add the new rows. Minimally-logged inserts use
          the bulk-loading mechanism, which allocates whole new pages/extents
          (and so does not need to read the target structure in the same way).





          Conclusion



          The conclusion being that the INSERT INTO is not able to use minimal logging, resulting in logging every inserted row individually in the log file of tempdb when used in combination with a global temp table / normal table.
          Whereas the local temp table/ SELECT INTO/ INSERT INTO ... WITH(TABLOCK) is able to use minimal logging.






          share|improve this answer

























            Your Answer








            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "182"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: false,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            imageUploader:
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            ,
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );













            draft saved

            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f233689%2flogical-reads-on-global-temp-table-but-not-on-session-level-temp-table%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            9














            Minimal logging is not being used when using INSERT INTO and global temp tables



            Inserting one million rows in a global temp table by using INSERT INTO



            INSERT INTO ##t1 (r)
            SELECT top(1000000) s1.r
            FROM dbo.s1
            CROSS APPLY dbo.s1 S2;


            When running SELECT * FROM fn_dblog(NULL, NULL) while the above query is executing, ~1M rows are returned.



            enter image description here



            One LOP_INSERT_ROW operation for each row + other
            log data.




            The same insert on a local temp table



            INSERT INTO #t1 (r)
            SELECT top(1000000) s1.r
            FROM dbo.s1
            CROSS APPLY dbo.s1 S2;


            Only going up to 700 rows returned by SELECT * FROM fn_dblog(NULL, NULL)



            enter image description here



            Minimal logging




            Inserting one million rows in a global temp table by using SELECT INTO



            SELECT top(1000000) s1.r
            INTO ##t2
            FROM dbo.s1
            CROSS APPLY dbo.s1 S2;


            enter image description here



            SELECT INTO a global temp table with 10k records



            SELECT s1.r
            INTO ##t2
            FROM dbo.s1;


            Time and IO Statistics



            SQL Server parse and compile time: 
            CPU time = 0 ms, elapsed time = 0 ms.
            Table 's1'. Scan count 1, logical reads 19, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

            SQL Server Execution Times:
            CPU time = 16 ms, elapsed time = 10 ms.
            SQL Server parse and compile time:
            CPU time = 0 ms, elapsed time = 0 ms.



            Based on this blogpost we can add TABLOCK to initiate minimal logging on a heap table



            INSERT INTO ##t1 WITH(TABLOCK) (r)
            SELECT s1.r
            FROM dbo.s1


            Low logical reads



            Table 's1'. Scan count 1, logical reads 19, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

            (10000 rows affected)



            Part of an answer by @PaulWhite on how to achieve minimal logging on temporary tables




            No. Local temporary tables (#temp) are private to the creating
            session, so a table lock hint is not required. A table lock hint would
            be required for a global temporary table (##temp) or a regular table
            (dbo.temp) created in tempdb, because these can be accessed from
            multiple sessions.




            Creating a regular table to test this:



            CREATE TABLE dbo.bla
            (
            r int NOT NULL
            );


            Filling it up with 1M records



            INSERT INTO bla 
            SELECT top(1000000)s1.r
            FROM dbo.s1
            CROSS APPLY dbo.s1 S2;


            >1M logical reads on this table



            Table 's1'. Scan count 17, logical reads 155, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
            Table 'bla'. Scan count 0, logical reads 1001607, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
            Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.



            Paul White's answer explaining the logical reads reported on the global temp table




            Generally, logical reads are reported for the target table when the
            insert is not minimally logged.



            These logical reads are associated with finding a place in the
            existing structure to add the new rows. Minimally-logged inserts use
            the bulk-loading mechanism, which allocates whole new pages/extents
            (and so does not need to read the target structure in the same way).





            Conclusion



            The conclusion being that the INSERT INTO is not able to use minimal logging, resulting in logging every inserted row individually in the log file of tempdb when used in combination with a global temp table / normal table.
            Whereas the local temp table/ SELECT INTO/ INSERT INTO ... WITH(TABLOCK) is able to use minimal logging.






            share|improve this answer





























              9














              Minimal logging is not being used when using INSERT INTO and global temp tables



              Inserting one million rows in a global temp table by using INSERT INTO



              INSERT INTO ##t1 (r)
              SELECT top(1000000) s1.r
              FROM dbo.s1
              CROSS APPLY dbo.s1 S2;


              When running SELECT * FROM fn_dblog(NULL, NULL) while the above query is executing, ~1M rows are returned.



              enter image description here



              One LOP_INSERT_ROW operation for each row + other
              log data.




              The same insert on a local temp table



              INSERT INTO #t1 (r)
              SELECT top(1000000) s1.r
              FROM dbo.s1
              CROSS APPLY dbo.s1 S2;


              Only going up to 700 rows returned by SELECT * FROM fn_dblog(NULL, NULL)



              enter image description here



              Minimal logging




              Inserting one million rows in a global temp table by using SELECT INTO



              SELECT top(1000000) s1.r
              INTO ##t2
              FROM dbo.s1
              CROSS APPLY dbo.s1 S2;


              enter image description here



              SELECT INTO a global temp table with 10k records



              SELECT s1.r
              INTO ##t2
              FROM dbo.s1;


              Time and IO Statistics



              SQL Server parse and compile time: 
              CPU time = 0 ms, elapsed time = 0 ms.
              Table 's1'. Scan count 1, logical reads 19, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

              SQL Server Execution Times:
              CPU time = 16 ms, elapsed time = 10 ms.
              SQL Server parse and compile time:
              CPU time = 0 ms, elapsed time = 0 ms.



              Based on this blogpost we can add TABLOCK to initiate minimal logging on a heap table



              INSERT INTO ##t1 WITH(TABLOCK) (r)
              SELECT s1.r
              FROM dbo.s1


              Low logical reads



              Table 's1'. Scan count 1, logical reads 19, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

              (10000 rows affected)



              Part of an answer by @PaulWhite on how to achieve minimal logging on temporary tables




              No. Local temporary tables (#temp) are private to the creating
              session, so a table lock hint is not required. A table lock hint would
              be required for a global temporary table (##temp) or a regular table
              (dbo.temp) created in tempdb, because these can be accessed from
              multiple sessions.




              Creating a regular table to test this:



              CREATE TABLE dbo.bla
              (
              r int NOT NULL
              );


              Filling it up with 1M records



              INSERT INTO bla 
              SELECT top(1000000)s1.r
              FROM dbo.s1
              CROSS APPLY dbo.s1 S2;


              >1M logical reads on this table



              Table 's1'. Scan count 17, logical reads 155, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
              Table 'bla'. Scan count 0, logical reads 1001607, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
              Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.



              Paul White's answer explaining the logical reads reported on the global temp table




              Generally, logical reads are reported for the target table when the
              insert is not minimally logged.



              These logical reads are associated with finding a place in the
              existing structure to add the new rows. Minimally-logged inserts use
              the bulk-loading mechanism, which allocates whole new pages/extents
              (and so does not need to read the target structure in the same way).





              Conclusion



              The conclusion being that the INSERT INTO is not able to use minimal logging, resulting in logging every inserted row individually in the log file of tempdb when used in combination with a global temp table / normal table.
              Whereas the local temp table/ SELECT INTO/ INSERT INTO ... WITH(TABLOCK) is able to use minimal logging.






              share|improve this answer



























                9












                9








                9







                Minimal logging is not being used when using INSERT INTO and global temp tables



                Inserting one million rows in a global temp table by using INSERT INTO



                INSERT INTO ##t1 (r)
                SELECT top(1000000) s1.r
                FROM dbo.s1
                CROSS APPLY dbo.s1 S2;


                When running SELECT * FROM fn_dblog(NULL, NULL) while the above query is executing, ~1M rows are returned.



                enter image description here



                One LOP_INSERT_ROW operation for each row + other
                log data.




                The same insert on a local temp table



                INSERT INTO #t1 (r)
                SELECT top(1000000) s1.r
                FROM dbo.s1
                CROSS APPLY dbo.s1 S2;


                Only going up to 700 rows returned by SELECT * FROM fn_dblog(NULL, NULL)



                enter image description here



                Minimal logging




                Inserting one million rows in a global temp table by using SELECT INTO



                SELECT top(1000000) s1.r
                INTO ##t2
                FROM dbo.s1
                CROSS APPLY dbo.s1 S2;


                enter image description here



                SELECT INTO a global temp table with 10k records



                SELECT s1.r
                INTO ##t2
                FROM dbo.s1;


                Time and IO Statistics



                SQL Server parse and compile time: 
                CPU time = 0 ms, elapsed time = 0 ms.
                Table 's1'. Scan count 1, logical reads 19, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

                SQL Server Execution Times:
                CPU time = 16 ms, elapsed time = 10 ms.
                SQL Server parse and compile time:
                CPU time = 0 ms, elapsed time = 0 ms.



                Based on this blogpost we can add TABLOCK to initiate minimal logging on a heap table



                INSERT INTO ##t1 WITH(TABLOCK) (r)
                SELECT s1.r
                FROM dbo.s1


                Low logical reads



                Table 's1'. Scan count 1, logical reads 19, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

                (10000 rows affected)



                Part of an answer by @PaulWhite on how to achieve minimal logging on temporary tables




                No. Local temporary tables (#temp) are private to the creating
                session, so a table lock hint is not required. A table lock hint would
                be required for a global temporary table (##temp) or a regular table
                (dbo.temp) created in tempdb, because these can be accessed from
                multiple sessions.




                Creating a regular table to test this:



                CREATE TABLE dbo.bla
                (
                r int NOT NULL
                );


                Filling it up with 1M records



                INSERT INTO bla 
                SELECT top(1000000)s1.r
                FROM dbo.s1
                CROSS APPLY dbo.s1 S2;


                >1M logical reads on this table



                Table 's1'. Scan count 17, logical reads 155, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
                Table 'bla'. Scan count 0, logical reads 1001607, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
                Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.



                Paul White's answer explaining the logical reads reported on the global temp table




                Generally, logical reads are reported for the target table when the
                insert is not minimally logged.



                These logical reads are associated with finding a place in the
                existing structure to add the new rows. Minimally-logged inserts use
                the bulk-loading mechanism, which allocates whole new pages/extents
                (and so does not need to read the target structure in the same way).





                Conclusion



                The conclusion being that the INSERT INTO is not able to use minimal logging, resulting in logging every inserted row individually in the log file of tempdb when used in combination with a global temp table / normal table.
                Whereas the local temp table/ SELECT INTO/ INSERT INTO ... WITH(TABLOCK) is able to use minimal logging.






                share|improve this answer















                Minimal logging is not being used when using INSERT INTO and global temp tables



                Inserting one million rows in a global temp table by using INSERT INTO



                INSERT INTO ##t1 (r)
                SELECT top(1000000) s1.r
                FROM dbo.s1
                CROSS APPLY dbo.s1 S2;


                When running SELECT * FROM fn_dblog(NULL, NULL) while the above query is executing, ~1M rows are returned.



                enter image description here



                One LOP_INSERT_ROW operation for each row + other
                log data.




                The same insert on a local temp table



                INSERT INTO #t1 (r)
                SELECT top(1000000) s1.r
                FROM dbo.s1
                CROSS APPLY dbo.s1 S2;


                Only going up to 700 rows returned by SELECT * FROM fn_dblog(NULL, NULL)



                enter image description here



                Minimal logging




                Inserting one million rows in a global temp table by using SELECT INTO



                SELECT top(1000000) s1.r
                INTO ##t2
                FROM dbo.s1
                CROSS APPLY dbo.s1 S2;


                enter image description here



                SELECT INTO a global temp table with 10k records



                SELECT s1.r
                INTO ##t2
                FROM dbo.s1;


                Time and IO Statistics



                SQL Server parse and compile time: 
                CPU time = 0 ms, elapsed time = 0 ms.
                Table 's1'. Scan count 1, logical reads 19, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

                SQL Server Execution Times:
                CPU time = 16 ms, elapsed time = 10 ms.
                SQL Server parse and compile time:
                CPU time = 0 ms, elapsed time = 0 ms.



                Based on this blogpost we can add TABLOCK to initiate minimal logging on a heap table



                INSERT INTO ##t1 WITH(TABLOCK) (r)
                SELECT s1.r
                FROM dbo.s1


                Low logical reads



                Table 's1'. Scan count 1, logical reads 19, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

                (10000 rows affected)



                Part of an answer by @PaulWhite on how to achieve minimal logging on temporary tables




                No. Local temporary tables (#temp) are private to the creating
                session, so a table lock hint is not required. A table lock hint would
                be required for a global temporary table (##temp) or a regular table
                (dbo.temp) created in tempdb, because these can be accessed from
                multiple sessions.




                Creating a regular table to test this:



                CREATE TABLE dbo.bla
                (
                r int NOT NULL
                );


                Filling it up with 1M records



                INSERT INTO bla 
                SELECT top(1000000)s1.r
                FROM dbo.s1
                CROSS APPLY dbo.s1 S2;


                >1M logical reads on this table



                Table 's1'. Scan count 17, logical reads 155, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
                Table 'bla'. Scan count 0, logical reads 1001607, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
                Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.



                Paul White's answer explaining the logical reads reported on the global temp table




                Generally, logical reads are reported for the target table when the
                insert is not minimally logged.



                These logical reads are associated with finding a place in the
                existing structure to add the new rows. Minimally-logged inserts use
                the bulk-loading mechanism, which allocates whole new pages/extents
                (and so does not need to read the target structure in the same way).





                Conclusion



                The conclusion being that the INSERT INTO is not able to use minimal logging, resulting in logging every inserted row individually in the log file of tempdb when used in combination with a global temp table / normal table.
                Whereas the local temp table/ SELECT INTO/ INSERT INTO ... WITH(TABLOCK) is able to use minimal logging.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Apr 1 at 23:22

























                answered Apr 1 at 22:20









                Randi VertongenRandi Vertongen

                4,8511924




                4,8511924



























                    draft saved

                    draft discarded
















































                    Thanks for contributing an answer to Database Administrators Stack Exchange!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid


                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.

                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f233689%2flogical-reads-on-global-temp-table-but-not-on-session-level-temp-table%23new-answer', 'question_page');

                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Adding axes to figuresAdding axes labels to LaTeX figuresLaTeX equivalent of ConTeXt buffersRotate a node but not its content: the case of the ellipse decorationHow to define the default vertical distance between nodes?TikZ scaling graphic and adjust node position and keep font sizeNumerical conditional within tikz keys?adding axes to shapesAlign axes across subfiguresAdding figures with a certain orderLine up nested tikz enviroments or how to get rid of themAdding axes labels to LaTeX figures

                    Luettelo Yhdysvaltain laivaston lentotukialuksista Lähteet | Navigointivalikko

                    Gary (muusikko) Sisällysluettelo Historia | Rockin' High | Lähteet | Aiheesta muualla | NavigointivalikkoInfobox OKTuomas "Gary" Keskinen Ancaran kitaristiksiProjekti Rockin' High