logical reads on global temp table, but not on session-level temp table The Next CEO of Stack OverflowGet 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

Are British MPs missing the point, with these 'Indicative Votes'?

How should I connect my cat5 cable to connectors having an orange-green line?

What difference does it make matching a word with/without a trailing whitespace?

How to find if SQL server backup is encrypted with TDE without restoring the backup

Find a path from s to t using as few red nodes as possible

MT "will strike" & LXX "will watch carefully" (Gen 3:15)?

Is the offspring between a demon and a celestial possible? If so what is it called and is it in a book somewhere?

pgfplots: How to draw a tangent graph below two others?

Is it reasonable to ask other researchers to send me their previous grant applications?

Salesforce opportunity stages

Free fall ellipse or parabola?

Small nick on power cord from an electric alarm clock, and copper wiring exposed but intact

How can I separate the number from the unit in argument?

How exploitable/balanced is this homebrew spell: Spell Permanency?

Why doesn't Shulchan Aruch include the laws of destroying fruit trees?

Why can't we say "I have been having a dog"?

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

Traveling with my 5 year old daughter (as the father) without the mother from Germany to Mexico

Early programmable calculators with RS-232

Planeswalker Ability and Death Timing

What did the word "leisure" mean in late 18th Century usage?

Strange use of "whether ... than ..." in official text

What does this strange code stamp on my passport mean?

Is a linearly independent set whose span is dense a Schauder basis?



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



The Next CEO of Stack OverflowGet 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










6















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


























    6















    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
























      6












      6








      6


      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 6 hours ago









      Max VernonMax Vernon

      52k13114230




      52k13114230




















          1 Answer
          1






          active

          oldest

          votes


















          5














          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









            5














            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





























              5














              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



























                5












                5








                5







                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 4 hours ago

























                answered 5 hours ago









                Randi VertongenRandi Vertongen

                4,211924




                4,211924



























                    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

                    How to create a command for the “strange m” symbol in latex? Announcing the arrival of Valued Associate #679: Cesar Manara Planned maintenance scheduled April 23, 2019 at 23:30 UTC (7:30pm US/Eastern)How do you make your own symbol when Detexify fails?Writing bold small caps with mathpazo packageplus-minus symbol with parenthesis around the minus signGreek character in Beamer document titleHow to create dashed right arrow over symbol?Currency symbol: Turkish LiraDouble prec as a single symbol?Plus Sign Too Big; How to Call adfbullet?Is there a TeX macro for three-legged pi?How do I get my integral-like symbol to align like the integral?How to selectively substitute a letter with another symbol representing the same letterHow do I generate a less than symbol and vertical bar that are the same height?

                    Българска екзархия Съдържание История | Български екзарси | Вижте също | Външни препратки | Литература | Бележки | НавигацияУстав за управлението на българската екзархия. Цариград, 1870Слово на Ловешкия митрополит Иларион при откриването на Българския народен събор в Цариград на 23. II. 1870 г.Българската правда и гръцката кривда. От С. М. (= Софийски Мелетий). Цариград, 1872Предстоятели на Българската екзархияПодмененият ВеликденИнформационна агенция „Фокус“Димитър Ризов. Българите в техните исторически, етнографически и политически граници (Атлас съдържащ 40 карти). Berlin, Königliche Hoflithographie, Hof-Buch- und -Steindruckerei Wilhelm Greve, 1917Report of the International Commission to Inquire into the Causes and Conduct of the Balkan Wars

                    Чепеларе Съдържание География | История | Население | Спортни и природни забележителности | Културни и исторически обекти | Религии | Обществени институции | Известни личности | Редовни събития | Галерия | Източници | Литература | Външни препратки | Навигация41°43′23.99″ с. ш. 24°41′09.99″ и. д. / 41.723333° с. ш. 24.686111° и. д.*ЧепелареЧепеларски Linux fest 2002Начало на Зимен сезон 2005/06Национални хайдушки празници „Капитан Петко Войвода“Град ЧепелареЧепеларе – народният ски курортbgrod.orgwww.terranatura.hit.bgСправка за населението на гр. Исперих, общ. Исперих, обл. РазградМузей на родопския карстМузей на спорта и скитеЧепеларебългарскибългарскианглийскитукИстория на градаСки писти в ЧепелареВремето в ЧепелареРадио и телевизия в ЧепелареЧепеларе мами с родопски чар и добри пистиЕвтин туризъм и снежни атракции в ЧепелареМестоположениеИнформация и снимки от музея на родопския карст3D панорами от ЧепелареЧепелареррр