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

Is it OK to decorate a log book cover?

Can Sri Krishna be called 'a person'?

Find the majority element, which appears more than half the time

Another proof that dividing by 0 does not exist -- is it right?

Gauss' Posthumous Publications?

How dangerous is XSS

Free fall ellipse or parabola?

Why did Batya get tzaraat?

The sum of any ten consecutive numbers from a fibonacci sequence is divisible by 11

"Eavesdropping" vs "Listen in on"

Does int main() need a declaration on C++?

Shortening a title without changing its meaning

Creating a script with console commands

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

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

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

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

Is there a rule of thumb for determining the amount one should accept for of a settlement offer?

Cannot restore registry to default in Windows 10?

What day is it again?

Could you use a laser beam as a modulated carrier wave for radio signal?

Can I cast Thunderwave and be at the center of its bottom face, but not be affected by it?

How can the PCs determine if an item is a phylactery?

Why was Sir Cadogan fired?



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










5















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


























    5















    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
























      5












      5








      5


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









      Max VernonMax Vernon

      52k13114230




      52k13114230




















          1 Answer
          1






          active

          oldest

          votes


















          4














          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









            4














            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





























              4














              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



























                4












                4








                4







                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 23 mins ago

























                answered 1 hour ago









                Randi VertongenRandi Vertongen

                4,201924




                4,201924



























                    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

                    Can not update quote_id field of “quote_item” table magento 2Magento 2.1 - We can't remove the item. (Shopping Cart doesnt allow us to remove items before becomes empty)Add value for custom quote item attribute using REST apiREST API endpoint v1/carts/cartId/items always returns error messageCorrect way to save entries to databaseHow to remove all associated quote objects of a customer completelyMagento 2 - Save value from custom input field to quote_itemGet quote_item data using quote id and product id filter in Magento 2How to set additional data to quote_item table from controller in Magento 2?What is the purpose of additional_data column in quote_item table in magento2Set Custom Price to Quote item magento2 from controller

                    Magento 2 disable Secret Key on URL's from terminal The Next CEO of Stack OverflowMagento 2 Shortcut/GUI tool to perform commandline tasks for windowsIn menu add configuration linkMagento oAuth : Generating access token and access secretMagento 2 security key issue in Third-Party API redirect URIPublic actions in admin controllersHow to Disable Cache in Custom WidgetURL Key not changing in Magento 2Product URL Key gets deleted when importing custom options - Magento 2Problem with reindex terminalMagento 2 - bin/magento Commands not working in Cpanel Terminal

                    Aasi (pallopeli) Navigointivalikko