| Max Mxdev's profileMax Ivak: сфераBlogListsNetwork | Help |
Max Ivak: сфера |
||||||||||||||||||
|
Perfomance: Transact-SQL Performance TuningGeneral Performance Guidelines// from book "The Guru's Guide to Transact-SQL", Ken Henderson• The best thing you can do to ensure the code you write performs optimally is to deepen the level of expertise on your development team. Good developers write good code. It pays to grow development talent through aggressive training. None of us was born knowing what a correlated subquery is. Investment in people often yields long-term benefits that are difficult if not impossible to obtain otherwise. • Identify and thoroughly investigate your application's key database operations and transactions as early in the development process as possible. Knowing these well early on and addressing them as soon as possible can mean the difference between a successful release and a fiasco. • Go into every project you build—from small ones to mammoth ones—assuming that no amount of performance tuning will rectify poor application or database design. It's essential to get these right up front. • Define performance requirements in terms of peak usage. Making a general statement like "The system must handle five hundred users" is not terribly useful. First, will all these users be logged in simultaneously? What's the peak number of users? Second, what will they be doing? When is the server likely to have to work hardest? When it comes to predicting real-world application performance, TPS benchmark numbers are relative indicators at best. Being as intimate as possible with the real stress points of your application is the key to success. The devil is in the details. • Keep in mind that sometimes perception dictates reality. This is particularly true with interactive applications. Sometimes it's more important to return control to an application quickly than to perform a query as efficiently as possible. The SELECT statement's FAST n hint allows you to return control quickly to the calling application, though using it may actually cause the query to take longer to run to completion. Using asynchronous cursors is another way to return quickly from a query (see Chapter 13, "Cursors," for more information). And remember that you can use the SET LOCK_TIMEOUT command to configure how long a query waits on a locked resource before timing out. This can prevent an app from appearing to hang while it waits on a resource. Even though a query may take longer overall to execute, returning control to the user in an expeditious manner can sometimes head off client machine reboots born of impatience or frustration. These reboots can affect performance themselves—especially if SQL Server and the application reside on the same machine. Thus perception directly affects reality. • Be sure to gauge performance extensively and often throughout the development process. Application performance testing is not a separable step that you can wait until after development to begin. It has to be an ongoing, fluid process that tracks the development effort closely. Application components should be prototyped, demonstrated, and benchmarked throughout the development process. It's better to know early on that a user finds performance unacceptable than to find out when you ship. • Thoroughly load test your app before shipping it. Load more data than your largest customer will require before you burn your first CD. If time permits, take your load testing to the next logical step and stress test the app—find out the magic values for data load, user connections, memory, and so on that cause it to fail or that exceed its capacity. Database Design Performance Tips Guru’s Guide to Transact-SQL 288 • Table row and key lengths should be as short as sensible. Be efficient, but don't be a miser. Trimming one byte per row isn't much of a savings if you have only a few rows, or, worse yet, you end up needing that one byte. The reason for narrow rows is obvious—the less work the server has to do to satisfy a query, the quicker it finishes. Using shorter rows allows more rows per page and more data in the same amount of cache space. This is also true for index pages—narrow keys allow more rows per page than wider ones. • Keeping clustered index keys as narrow as possible will help reduce the size of nonclustered indexes since they now reference the clustered index (if one exists) rather than referencing the table directly. • Begin by normalizing every database you build at least to third normal form. You can denormalize the design later if the need arises. See the "Denormalization" section later in this chapter for further information. • Use Declarative Referential Integrity constraints to ensure relational integrity when possible because they're generally faster than triggers and stored procedures. DRI constraints cause highly optimized native machine code internal to SQL Server to run. Triggers and stored procedures, by contrast, consist of pseudocompiled Transact-SQL code. All other things being equal, native machine code is clearly the better performer of the two. • Use fixed-length character data types when the length of a column's data doesn't vary significantly throughout a table. Processing variable-length columns requires more processing resources than handling fixed-length columns. • Disallow NULLs when possible—handling NULLs adds extra overhead to storage and query processing. It's not unheard of for developers to avoid NULLs altogether, using placeholders to signify missing values as necessary. • Consider using filegroups to distribute large tables over multiple drives and to separate indexes from data. If possible, locate the transaction log on a separate drive or drives from the filegroups that compose the database, and separate key tables from one another. This is especially appropriate for very large database (VLDB) implementations. • If the primary key for a given table is sequential (e.g., an identity column), consider making it a nonclustered primary key. A clustered index on a monotonically increasing key is less than optimal since you probably won't ever query the table for a range of key values or use the primary key column(s) with ORDER BY. A clustered sequential primary key can cause users to contend for the same area of the database as they add rows to the table, creating what's known as a "hotspot." Avoid this if you can by using clustered keys that sort the data more evenly across the table. • If a table frequently experiences severe contention, especially when multiple users are attempting to insert new rows, page locks may be at fault. Consider using the sp_indexoptions system stored procedure to disable page locks on the suspect table. Disabling page locks forces the server to use row locks and table locks. This will prevent the automatic escalation of row locks to page locks from reducing concurrency. • Use computed columns to render common column calculations rather than deriving them via SQL each time you query a table. This is syntactically more compact, reduces the work required to generate an execution plan, and cuts down on the SQL that must traverse the network for routine queries. • Test your database with different row volumes in order to get a feel for the amount of data the design will support. This will let you know early on what the capacity of your model is, possibly pointing out serious problems in the design. A database that works fine for a few thousand rows may collapse miserably under the weight of a few million. • When all else fails, consider limited database denormalization to improve performance. See the "Denormalization" section later in this chapter for more information. Index Performance Tips • Create indexes the query optimizer can use. Generally speaking, clustered indexes are best for range selections and ordered queries. Clustered indexes are also appropriate for keys with a high density (those with many duplicate values). Since rows are physically sorted, queries that search using these nonunique values will find them with a minimum number of I/O operations. Nonclustered indexes are better for singleton selects and individual row lookups. • Make nonclustered indexes as highly selective (i.e., with as low densities) as possible. Index selectivity can be calculated using the formula Selectivity = # of Unique Keys / # of Rows. Nonclustered indexes with a selectivity less than 0.1 are not efficient, and the optimizer will refuse to Chapter 16. Transact-SQL Performance Tuning 289 use them. Nonclustered indexes are best used to find single rows. Obviously, duplicate keys force the server to work harder to locate a particular row. • Along the lines of making indexes highly selective, order the key columns in a multicolumn index by selectivity, placing more selective columns first. As the server traverses the index tree to find a given key column value, the use of highly selective key columns means that it will have to perform fewer I/Os to reach the leaf level of the index, resulting in a faster query. • Keep key database operations and transactions in mind as you construct indexes. Build indexes that the query optimizer can use to service your more crucial transactions. • Consider creating indexes to service popular join conditions. If you frequently join two tables on a set of columns, consider building an index to speed the join. • Drop indexes that aren't being used. If you inspect the execution plans for the queries that should be using an index and find that the index can't be used as is, consider getting rid of it. Redesign it if that makes sense, or simply omit it—whatever works best in your particular situation. • Consider creating indexes on foreign key references. Foreign keys require a unique key index on the referenced table but make no index stipulations on the table making the reference. Creating an index on the dependent table can speed up foreign key integrity checks that result from modifications to the referenced table and can improve join performance between the two tables. • Create temporary indexes to service infrequent reports and user queries. A report that's run only annually or semiannually may not merit an index that has to be maintained year-round. Consider creating the index just before you run the report and dropping it afterward if that's faster than running the report without the index. • It may be advantageous to drop and recreate indexes during BULK INSERT operations. BULK INSERT operations, especially those involving multiple clients, will generally be faster when indexes aren't present. This is no longer the maxim it once was, but common sense tells us the less work that has to occur during a bulk load, the faster it should be. • If the optimizer can retrieve all the data it needs from a nonclustered index without having to reference the underlying table, it will do so. This is called index covering, and indexes that facilitate it are known as covered indexes. If adding a small column or columns to an existing nonclustered index would give it all the data a popular query needs, you may find that it speeds up the query significantly. Covered indexes are the closest you'll get to having multiple clustered indexes on the same table. • Allow SQL Server to maintain index statistic information for your databases automatically. This helps ensure that it's kept reasonably up to date and alleviates the need by most apps to rebuild index statistics manually. • Because SQL Server's automatic statistics facility uses sampling to generate statistical info as quickly as possible, it may not be as representative of your data as it could be. If the query optimizer elects not to use indexes that you think it should be using, try updating the statistics for the index manually using UPDATE STATISTICS...WITH FULLSCAN. • You can use DBCC DBREINDEX() to rebuild the indexes on a table. This is one way of removing dead space from a table or changing the FILLFACTOR of one of its indexes. Here's an example: • • DBCC DBREINDEX('Customers','PK_Customers') • DBCC DBREINDEX('Customers','',100) • Both of these examples cause all indexes on the Northwind Customers table to be rebuilt. In the first example, we pass the name of the clustered index into DBREINDEX. Rebuilding its clustered index rebuilds a table's nonclustered indexes as well. In the second example, we pass an empty string for the index name. This also causes all indexes on the table to be rebuilt. The nice thing about DBREINDEX is that it's atomic—either the specified index or indexes are all dropped and recreated or none of them are. This includes indexes set up by the server to maintain constraints, such as primary and unique keys. In fact, DBREINDEX is the only way to rebuild primary and unique key indexes without first dropping their associated constraints. Since other tables may depend upon a table's primary or unique key, this can get quite complicated. Fortunately, Guru’s Guide to Transact-SQL 290 DBREINDEX takes care of it automatically—it can drop and recreate any of a table's indexes regardless of dependent tables and constraints. • You can use DBCC SHOWCONTIG to list fragmentation information for a table and its indexes. You can use this info to decide whether to reorganize the table by rebuilding its clustered index. • As mentioned in the section "Database Design Performance Tips," if an index regularly experiences a significant level of contention during inserts by multiple users, page locking may be the culprit. Consider using the sp_indexoptions system procedure to disable page locks for the index. Disabling page locks forces the server to use row locks and table locks. As long as row locks do not escalate to table locks inordinately often, this should result in improved concurrency. • Thanks to the query optimizer's use of multiple indexes on a single table, multiple single-key indexes can yield better overall performance than a compound-key index. This is because the optimizer can query the indexes separately and then merge them to return a result set. This is more flexible than using a compound-key index because the single-column index keys can be specified in any combination. That's not true with a compound key—you must use compound-key columns in a left-toright order. • Use the Index Tuning Wizard to suggest the optimal indexes for queries. This is a sophisticated tool that can scan SQL Profiler trace files to recommend indexes that may improve performance. You can access it via the Management|Index Tuning Wizard option on the Tools|Wizards menu in Enterprise Manager or the Perform Index Analysis option on the Query menu in Query Analyzer. SELECT Performance Tips • Match query search columns with those leftmost in the index when possible. An index on stor_id, ord_num will not be of any help to a query that filters results on the ord_num column. • Construct WHERE clauses that the query optimizer can recognize and use as search arguments. See the "SARGs" section later for more information. • Don't use DISTINCT or ORDER BY "just in case." Use them if you need to remove duplicates or if you need to guarantee a particular result set order, respectively. Unless the optimizer can locate an index to service them, they can force the creation of an intermediate work table, which can be expensive in terms of performance. • Use UNION ALL rather than UNION when you don't care about removing duplicates from a UNIONed result set. Because it removes duplicates, UNION must sort or hash the result set before returning it. Obviously, if you can avoid this, you can improve performance—sometimes dramatically. • As mentioned earlier, you can use SET LOCK_TIMEOUT to control the amount of time a connection waits on a blocked resource. At session startup, @@LOCK_TIMEOUT returns –1, which means that no timeout value has been set yet. You can set LOCK_TIMEOUT to a positive integer to control the number of milliseconds a query will wait on a blocked resource before timing out. In highly contentious environments, this is sometimes necessary to prevent applications from appearing to hang. • If a query includes an IN predicate that contains a list of constant values (rather than a subquery), order the values based on frequency of occurrence in the outer query, if you know the bias of your data well enough. A common approach is to order the values alphabetically or numerically, but that may not be optimal. Since the predicate returns true as soon as any of its values match, moving those that appear more often to the first of the list should speed up the query, especially if the column being searched is not indexed. • Give preference to joins over nested subqueries. A subquery can require a nested iteration—a loop within a loop. During a nested iteration, the rows in the inner table are scanned for each row in the outer table. This works fine for smaller tables and was the only join strategy supported by SQL Server until version 7.0. However, as tables grow larger, this approach becomes less and less efficient. It's far better to perform normal joins between tables and let the optimizer decide how best to process them. The optimizer will usually take care of flattening unnecessary subqueries into joins, but it's always better to write efficient code in the first place. • Avoid CROSS JOINs if you can. Unless you actually need the cross product of two tables, use a more succinct join form to relate one table to another. Returning an unintentional Cartesian product and then removing the duplicates it generates using DISTINCT or GROUP BY are a common problem among beginners and a frequent cause of serious query performance problems. Chapter 16. Transact-SQL Performance Tuning 291 • You can use the TOP n extension to restrict the number of rows returned by a query. This is particularly handy when assigning variables using a SELECT statement because you may wish to see values from the first row of a table only. • You can use the OPTION clause of a SELECT statement to influence the query optimizer directly through query hints. You can also specify hints for specific tables and joins. As a rule, you should allow the optimizer to optimize your queries, but you may run into situations where the execution plan it selects is less than ideal. Using query, table, and join hints, you can force a particular type of join, group, or union, the use of a particular index and so on. The section on the Transact-SQL SELECT statement in the Books Online documents the available hints and their effects on queries. • If you are benchmarking one query against another to determine the most efficient way to access data, be sure to keep SQL Server's caching mechanisms from skewing your test results. One way to do this is to cycle the server between query runs. Another is to use undocumented DBCC command verbs to clear out the relevant caches. DBCC FREEPROCCACHE frees the procedure cache; DBCC DROPCLEANBUFFERS clears all caches. INSERT Performance Tips • Because individual row inserts aren't logged, SELECT...INTO is often many times faster than a regular logged INSERT. It locks system tables, so use it with care. If you use SELECT...INTO to create a large table, other users may be unable to create objects in your database until the SELECT...INTO completes. This has particularly serious implications for tempdb because it can prevent users from creating temporary objects that might very well wreak havoc with your apps, lead to angry mobs with torches, and cause all sorts of panic and mayhem. That's not to say that you shouldn't use SELECT...INTO—just be careful not to monopolize a database when you do. • BULK INSERT is faster than INSERT for loading external data, even when fully logged, because it operates at a lower level within the server. Use it rather than lengthy INSERT scripts to load large quantities of data onto the server. SQL Server - Dos and Books-- Hands-On SQL Server – Troubleshooting: Locking and Blocking Kalen Delaney книга рассказывает о блокировках со всех сторон Blocking and Indexes: How do indexes affect locking and blocking? How do indexes affect locking and blocking? // from Hands-On SQL Server – Locking and Blocking – Kalen Delaney In general, having good indexes will help reduce blocking problems, because it will help reduce the overall time of query execution. The faster a query can complete, and the transaction containing it is committed, the faster any locks acquired can be released. Most serious blocking problems are due to locks being held for a long time, so anything you can do to minimize the time that locks are held is a good thing. A related aspect in which proper indexing can help avoid blocking problems can be observed in Hands-On Exercise #6C. This example shows that without any index, a simple select can block on a row other than the row it is trying to access. You might think that this wasn’t possible if SQL Server truly supports row locking, but without an index, SQL Server has no way to know what data is in the locked row, and doesn’t know whether the locked row is actually the one it needs to access. When we change the query to add a nonclustered index to the table, the index gives SQL Server enough information to know that it can ignore the locked row, and directly access the row that is indicated in the WHERE clause of the SELECT statement. Hands-On #6C: Use of Index Avoids Blocking -- Use Query Analyzer for this Exercise, -- Close all existing connections and start a new one -- Step 1: Create and populate a small heap table USE pubs GO DROP TABLE t1 GO CREATE TABLE t1 (a int) GO INSERT INTO t1 VALUES (1) INSERT INTO t1 VALUES (3) INSERT INTO t1 VALUES (5) GO -- Step 2: Update a single row BEGIN TRAN UPDATE t1 SET a = 7 WHERE a = 1 GO EXEC sp_lock GO -- The output here should show you one X lock, on a RID; -- that is the row that has been updated. -- Step 2: In another query window, run a batch that -- tries to select a completely different row than -- the one that is being updated USE pubs SELECT * FROM t1 WHERE a = 3 GO -- The above SELECT should block. -- Step 3: Return to the first query window. -- Examine sp_lock again and note that the second process -- is waiting for a lock on the same RID that was locked -- in Step 2. EXEC sp_lock GO ROLLBACK TRAN GO -- Step 4: Stay in the same query window, and change the -- script slightly to create an index on column ‘a’ Hands-On SQL Server – Locking and Blocking – Kalen Delaney Page 74 USE pubs GO DROP TABLE t1 GO -- Create and populate the same small table CREATE TABLE t1 ( a int) GO -- Build an index on the table CREATE INDEX idx1 ON t1(a) GO -- Insert the same three rows into the table INSERT INTO t1 VALUES (1) INSERT INTO t1 VALUES (3) INSERT INTO t1 VALUES (5) GO -- Step 5 : Update a single row and look at the locks BEGIN TRAN UPDATE t1 SET a = 7 WHERE a = 1 EXEC sp_lock -- Now the output should show you three X locks -- one again on a RID and two KEY locks. -- When the key column a is updated, the leaf level of -- the nonclustered index is adjusted. -- Since the leaf level of the index keeps all the keys -- in sorted order, the old key with the value 1 is moved -- from the beginning of the leaf level to the end, -- because now its value is 7. However, until the -- transaction is over, a ghost entry is left in the -- original position and the key lock is maintained. -- So there are two key locks: one for the old value -- and one for the new. -- Step 6: In another query window, run a batch that -- tries to select a completely different row than -- the one that is being updated USE pubs SELECT * FROM t1 WHERE a = 3 GO -- The above SELECT will NOT block. -- Step 7: Return to the first query window and rollback ROLLBACK TRAN GO Another benefit to having indexes on a table is that there is one more option for controlling the types of locks SQL Server will acquire. The stored procedure sp_indexoption lets you manually control the unit of locking by letting you disallow page locks or row locks within an index. Since these options are available only for indexes, there is no way to control the locking within the data pages of a heap. But remember that if a table has a clustered index, the data pages are part of the index and are affected by the sp_indexoption setting for the clustered index. The index options are set for each table or index individually. Two options, ‘AllowRowLocks’ and ‘AllowPageLocks’, are both set to TRUE initially for every table and index. If both of these options are set to FALSE for a table, only full table locks are allowed. Note that there is no option to disallow table locks; that option must always be available. To verify whether row or page locks have been disallowed, you can use the indexproperty function. We can disable row locks by either setting the ‘AllowRowLocks’ option to false, or by setting the ‘DisAllowRowLocks’ option to true. There are two related options for page locks: ‘AllowPageLocks’ and ‘DisAllowPageLocks’. However, there is only one parameter we can use to check whether row locks are allowed and one to check whether page locks are allowed. The following command checks whether row locks have been disallowed on the authors table by supplying the name of the clustered index on the authors table. The INDEXPROPERTY function can return 3 values: 1 means row locks are disallowed, 0 means they are allowed, and NULL means we typed something incorrectly. SELECT INDEXPROPERTY (object_id('authors'), 'UPKCL_auidind','IsRowLockDisallowed') To change the value so that row locks will no longer be allowed on the authors table, we can run either of the following two commands: EXEC sp_indexoption 'authors.UPKCL_auidind', 'AllowRowLocks', false EXEC sp_indexoption 'authors.UPKCL_auidind', 'DisAllowRowLocks', true Low-Level Keyboard HookLow-Level Keyboard Hook in C#References http://blogs.msdn.com/toub/archive/2006/05/03/589423.aspx http://www.developer.com/net/vb/article.php/2193301 http://eknowledger.spaces.live.com/blog/cns!F475D4DE444DB1AB!695.entry?fl=cat Simulate Mouse and Keyboard Events in CodeHow to: Simulate Mouse and Keyboard Events in Codeoverview:SendKeys.Send("{ENTER}");http://msdn.microsoft.com/en-us/library/system.windows.forms.sendkeys.send.aspx WebBrowser - Clear the CacheHOW TO: Clear the Cache When Your Application Hosts a WebBrowser Control in Visual C# .NETread MSDN article http://support.microsoft.com/kb/q326201/ UrlEncode - Encoding Values Of Form FieldsUrlEncode - Encoding Values Of Form FieldsAbstractHttpUtility.UrlEncode Description: HttpUtility.UrlEncode A string encoded with UrlEncode can be safely POSTed to another page.Examples: string EncodedString = HttpUtility.UrlEncode("This is a <Test String>."); References1. RFC 1738: Uniform Resource Locators (URL) specificationhttp://www.blooberry.com/indexdot/html/topics/urlencoding.htm Закладки - сайты Сайты с интересными цветами (гаммой) 1. http://www.shinyshiny.tv/ розовый цвет вверху.. Google - always BETA? Does Google test its sites? availability of its pages? broken links? Or its services are always BETA.. New blogsearch service has launched http://blogsearch.google.com/ But try to access about pages: 1. http://www.google.com/intl/ru/help/about_blogsearch.html click on Services on the left we go here http://www.google.com/terms.html and the page "http://www.google.com/terms.html" is NOT available: Not FoundThe requested URL/terms.html was not found on this server.Is it too hard to use some tool to check all broken links? this page http://www.google.com/intl/ru/help/about_blogsearch.html has not a lot of content and functionality.. my favourite 3d screensavers
|
|
||||||||||||||||
|
|