In general, is there a performance difference between using table variables and using temporary tables in SQL Server 2000?
There can be a big performance difference between using table variables and temporary tables. In most cases, temporary tables are faster than table variables. I took the following tip from the private SQL Server MVP newsgroup and received permission from Microsoft to share it with you. One MVP noticed that although queries using table variables didn't generate parallel query plans on a large SMP box, similar queries using temporary tables (local or global) and running under the same circumstances did generate parallel plans.
A senior member of the SQL Server development team told me that table variables use internal metadata in a way that prevents the engine from using a table variable within a parallel query. He also said that SQL Server maintains statistics for queries that use temporary tables but not for queries that use table variables. Without statistics, SQL Server might choose a poor processing plan for a query that contains a table variable. The development team member added that you should limit your use of SQL Server 2000 table variables to reasonably small queries and data sets and use temporary tables for larger data sets.
This advice about table variables contradicts some past Microsoft information, which said that table variables were faster because they're created in memory. However, table variables can incur disk I/O in ways similar to temporary tables.
In deciding whether you should use table variables or temporary tables, benchmark both in your environment. I suspect that temporary tables will provide better performance on larger result sets in most cases. For more information about table variables, see the Microsoft article "INF: Frequently Asked Questions—SQL Server 2000—Table Variables".
A local temporary table, #table_name, exists only for the duration of a user
session or the procedure that created the temporary table. When the user logs
off or when the procedure that created the table completes, the local temporary
table is lost. Multiple users can't share a local temporary table because it is
local to one user session. You also can't grant or revoke permissions on the
local temporary table.
A global temporary table, ##table_name, also exists for the duration of a user
session or the procedure that created the table. When the last user session
that references the table disconnects, the global temporary table is lost.
However, multiple users can access a global temporary table; in fact, all other
database users can access it. But you can't grant or revoke permissions on the
global temporary table because it's always available to everyone.
Local and
global temporary tables differ in a subtle way. Let's look at what SQL ServerBooks Online (BOL) says about temporary tables.
"Temporary tables are similar to permanent tables, except temporary tables
are stored in tempdb and are deleted automatically when no longer in use. The
two types of temporary tables, local and global, differ from each other in
their names, their visibility, and their lifetimes." The local table we
created in our procedure by using sp_executesql won't be accessible to either
the procedure or its child procedures. Within its execution scope, an
sp_executesql system stored procedure creates and drops a local table. By
definition, when the sp_executesql procedure ends, the life of the table also
ends—hence the need to create a global temporary table.
I listened intently to the new Oracle programmer as he described all the struggles he's been having on his first big project. As I've done many times already in his short career, I interrupt with some words of wisdom.
"It's time to add Global Temporary Tables to your toolbelt."
"What are those?" he asks, as he opens the directory with the Oracle documentation. I smile. He has already learned where I always send him first.
"They're the ultimate work tables," I continue. "They're permanent tables, where you can add and modify session-specific data without affecting other sessions."
"What's so special about that?" he asks. "Even with regular tables, you can add and modify the data all you want without affecting other sessions. Just don't commit, and remember to rollback when your session is done."
"Oh yeah? And what about all the persistent work you're doing in your session? How do you commit that?"
"Oh yeah. Does it allow for indexes, and triggers, and views with regular tables?"
"Yep, all of that. See for yourself, it's easy. You've got the manual in front of you, so you drive."
Then I watched as he opened one session, and created a global temporary table.
He opened another session and was pleased to see the table there. He then added a row in the first session, committed it, and was planning to use the other session to see if the data was there. But instead he was in for a little surprise.
"Hey!" he shouted. Heads popped up in nearby cubicles. "Where did it go?"
"Keep reading," I said, gesturing towards the "ON COMMIT" options for Global Temporary Tables. "By default, every time you commit your data, it is assumed that you want to clear out your work tables. Try PRESERVE."
He dropped the table, and tried again.
"That's better," he smiled. Now let's check the other session.
"Excellent. So this data will remain there until my session ends?"
"Yep. Try it." He exited his session, logged back in, and sure enough the data was gone. "This is great. But what if I want to get rid of the data at some point in my session?"
"Truncate. Truncating the work table will only truncate the data in your session, not all the data."
"Hey neat. Thanks, this will be very useful. What are you doing for lunch later?"
"Aren't you even going to try it? What, you're just going to trust me?" I said. I think he was a little surprised that I would I'd rather talk about work tables than lunch. Frankly, so am I. Thankfully, he worked quickly, typing first in his second session.
"I don't think you need all those commits," I laughed. "But ok, now look back in your first session. If the row you added previously isn't there, then I'm a big fat liar. Otherwise, we can talk about lunch."
I listened intently to the new Oracle programmer as he described all the struggles he's been having on his first big project. As I've done many times already in his short career, I interrupt with some words of wisdom.
"It's time to add Global Temporary Tables to your toolbelt."
"What are those?" he asks, as he opens the directory with the Oracle documentation. I smile. He has already learned where I always send him first.
"They're the ultimate work tables," I continue. "They're permanent tables, where you can add and modify session-specific data without affecting other sessions."
"What's so special about that?" he asks. "Even with regular tables, you can add and modify the data all you want without affecting other sessions. Just don't commit, and remember to rollback when your session is done."
"Oh yeah? And what about all the persistent work you're doing in your session? How do you commit that?"
"Oh yeah. Does it allow for indexes, and triggers, and views with regular tables?"
"Yep, all of that. See for yourself, it's easy. You've got the manual in front of you, so you drive."
Then I watched as he opened one session, and created a global temporary table.
SQL> CREATE GLOBAL TEMPORARY TABLE worktable (x NUMBER(3)); Table created.
He opened another session and was pleased to see the table there. He then added a row in the first session, committed it, and was planning to use the other session to see if the data was there. But instead he was in for a little surprise.
SQL> INSERT INTO worktable (x) VALUES (1); 1 row created. SQL> SELECT * FROM worktable; X ---------- 1 SQL> commit; Commit complete. SQL> SELECT * FROM worktable; no rows selected
"Hey!" he shouted. Heads popped up in nearby cubicles. "Where did it go?"
"Keep reading," I said, gesturing towards the "ON COMMIT" options for Global Temporary Tables. "By default, every time you commit your data, it is assumed that you want to clear out your work tables. Try PRESERVE."
He dropped the table, and tried again.
SQL> CREATE GLOBAL TEMPORARY TABLE worktable 2 (x NUMBER(3)) 3 ON COMMIT PRESERVE ROWS; Table created. SQL> INSERT INTO worktable (x) VALUES (1); 1 row created. SQL> SELECT * FROM worktable; X ---------- 1 SQL> commit; Commit complete. SQL> SELECT * FROM worktable; X ---------- 1
"That's better," he smiled. Now let's check the other session.
SQL> SELECT * FROM worktable; no rows selected
"Excellent. So this data will remain there until my session ends?"
"Yep. Try it." He exited his session, logged back in, and sure enough the data was gone. "This is great. But what if I want to get rid of the data at some point in my session?"
"Truncate. Truncating the work table will only truncate the data in your session, not all the data."
"Hey neat. Thanks, this will be very useful. What are you doing for lunch later?"
"Aren't you even going to try it? What, you're just going to trust me?" I said. I think he was a little surprised that I would I'd rather talk about work tables than lunch. Frankly, so am I. Thankfully, he worked quickly, typing first in his second session.
SQL> INSERT INTO worktable (x) VALUES (2) 1 row created. SQL> commit; Commit complete. SQL> SELECT * FROM worktable; X ---------- 2 SQL> TRUNCATE TABLE worktable; Table truncated. SQL> SELECT * FROM worktable; no rows selected SQL> commit; Commit complete.
"I don't think you need all those commits," I laughed. "But ok, now look back in your first session. If the row you added previously isn't there, then I'm a big fat liar. Otherwise, we can talk about lunch."
SQL> SELECT * FROM worktable; X ---------- 1
No comments:
Post a Comment