100% found this document useful (1 vote)
55 views

SQL Server 2017 Query Performance Tuning: troubleshoot and optimize query performance Fifth Edition Grant Fritchey All Chapters Instant Download

performance

Uploaded by

micksmowen00
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
55 views

SQL Server 2017 Query Performance Tuning: troubleshoot and optimize query performance Fifth Edition Grant Fritchey All Chapters Instant Download

performance

Uploaded by

micksmowen00
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 49

Download the Full Version of textbook for Fast Typing at textbookfull.

com

SQL Server 2017 Query Performance Tuning:


troubleshoot and optimize query performance Fifth
Edition Grant Fritchey

https://textbookfull.com/product/sql-server-2017-query-
performance-tuning-troubleshoot-and-optimize-query-
performance-fifth-edition-grant-fritchey/

OR CLICK BUTTON

DOWNLOAD NOW

Download More textbook Instantly Today - Get Yours Now at textbookfull.com


Recommended digital products (PDF, EPUB, MOBI) that
you can download immediately if you are interested.

Query Store for SQL Server 2019 1st Edition Tracy Boggiano
Grant Fritchey

https://textbookfull.com/product/query-store-for-sql-server-2019-1st-
edition-tracy-boggiano-grant-fritchey/

textboxfull.com

SQL Server Execution Plans For SQL Server 2008 through to


2017 and Azure SQL Database 3rd Edition Grant Fritchey

https://textbookfull.com/product/sql-server-execution-plans-for-sql-
server-2008-through-to-2017-and-azure-sql-database-3rd-edition-grant-
fritchey/
textboxfull.com

BizTalk Server 2016: Performance Tuning and Optimization


Agustín Mántaras

https://textbookfull.com/product/biztalk-server-2016-performance-
tuning-and-optimization-agustin-mantaras/

textboxfull.com

Query Store for SQL Server 2019: Identify and Fix Poorly
Performing Queries 1st Edition Tracy Boggiano

https://textbookfull.com/product/query-store-for-sql-
server-2019-identify-and-fix-poorly-performing-queries-1st-edition-
tracy-boggiano/
textboxfull.com
SQL Cookbook: Query Solutions and Techniques for All SQL
Users 2nd Edition Anthony Molinaro

https://textbookfull.com/product/sql-cookbook-query-solutions-and-
techniques-for-all-sql-users-2nd-edition-anthony-molinaro/

textboxfull.com

Learning Apache Drill Query and Analyze Distributed Data


Sources with SQL 1st Edition Charles Givre

https://textbookfull.com/product/learning-apache-drill-query-and-
analyze-distributed-data-sources-with-sql-1st-edition-charles-givre/

textboxfull.com

High Performance SQL Server: The Go Faster Book 1st


Edition Benjamin Nevarez (Auth.)

https://textbookfull.com/product/high-performance-sql-server-the-go-
faster-book-1st-edition-benjamin-nevarez-auth/

textboxfull.com

Refactoring Legacy T SQL for Improved Performance Modern


Practices for SQL Server Applications 1st Edition Lisa
Bohm
https://textbookfull.com/product/refactoring-legacy-t-sql-for-
improved-performance-modern-practices-for-sql-server-applications-1st-
edition-lisa-bohm/
textboxfull.com

High Performance SQL Server: Consistent Response for


Mission-Critical Applications 2nd Edition Benjamin Nevarez

https://textbookfull.com/product/high-performance-sql-server-
consistent-response-for-mission-critical-applications-2nd-edition-
benjamin-nevarez/
textboxfull.com
SQL Server 2017
Query Performance
Tuning
Troubleshoot and Optimize Query
Performance

Fifth Edition

Grant Fritchey
SQL Server 2017 Query
Performance Tuning
Troubleshoot and Optimize Query
Performance
Fifth Edition

Grant Fritchey
SQL Server 2017 Query Performance Tuning
Grant Fritchey
Grafton, Massachusetts, USA

ISBN-13 (pbk): 978-1-4842-3887-5 ISBN-13 (electronic): 978-1-4842-3888-2


https://doi.org/10.1007/978-1-4842-3888-2
Library of Congress Control Number: 2018955582

Copyright © 2018 by Grant Fritchey


This work is subject to copyright. All rights are reserved by the Publisher, whether the whole or part of the
material is concerned, specifically the rights of translation, reprinting, reuse of illustrations, recitation,
broadcasting, reproduction on microfilms or in any other physical way, and transmission or information
storage and retrieval, electronic adaptation, computer software, or by similar or dissimilar methodology now
known or hereafter developed.
Trademarked names, logos, and images may appear in this book. Rather than use a trademark symbol with
every occurrence of a trademarked name, logo, or image we use the names, logos, and images only in an
editorial fashion and to the benefit of the trademark owner, with no intention of infringement of the
trademark.
The use in this publication of trade names, trademarks, service marks, and similar terms, even if they are not
identified as such, is not to be taken as an expression of opinion as to whether or not they are subject to
proprietary rights.
While the advice and information in this book are believed to be true and accurate at the date of publication,
neither the authors nor the editors nor the publisher can accept any legal responsibility for any errors or
omissions that may be made. The publisher makes no warranty, express or implied, with respect to the
material contained herein.
Managing Director, Apress Media LLC: Welmoed Spahr
Acquisitions Editor: Jonathan Gennick
Development Editor: Laura Berendson
Coordinating Editor: Jill Balzano
Cover designed by eStudioCalamar
Cover image designed by Freepik (www.freepik.com)
Distributed to the book trade worldwide by Springer Science+Business Media New York, 233 Spring Street,
6th Floor, New York, NY 10013. Phone 1-800-SPRINGER, fax (201) 348-4505, e-mail orders-ny@springer-
sbm.com, or visit www.springeronline.com. Apress Media, LLC is a California LLC and the sole member
(owner) is Springer Science + Business Media Finance Inc (SSBM Finance Inc). SSBM Finance Inc is a
Delaware corporation.
For information on translations, please e-mail [email protected], or visit www.apress.com/
rights-permissions.
Apress titles may be purchased in bulk for academic, corporate, or promotional use. eBook versions and
licenses are also available for most titles. For more information, reference our Print and eBook Bulk Sales
web page at www.apress.com/bulk-sales.
Any source code or other supplementary material referenced by the author in this book is available to
readers on GitHub via the book's product page, located at www.apress.com/9781484238875. For more
detailed information, please visit www.apress.com/source-code.
Printed on acid-free paper
To my family. Thank you.
Table of Contents
About the Author���������������������������������������������������������������������������������������������������xxv

About the Technical Reviewer�����������������������������������������������������������������������������xxvii


Acknowledgments������������������������������������������������������������������������������������������������xxix

Introduction����������������������������������������������������������������������������������������������������������xxxi

Chapter 1: SQL Query Performance Tuning��������������������������������������������������������������� 1


The Performance Tuning Process������������������������������������������������������������������������������������������������� 3
The Core Process��������������������������������������������������������������������������������������������������������������������� 3
Iterating the Process��������������������������������������������������������������������������������������������������������������� 7
Performance vs. Price����������������������������������������������������������������������������������������������������������������� 10
Performance Targets������������������������������������������������������������������������������������������������������������� 10
“Good Enough” Tuning����������������������������������������������������������������������������������������������������������� 11
Performance Baseline����������������������������������������������������������������������������������������������������������������� 11
Where to Focus Efforts���������������������������������������������������������������������������������������������������������������� 13
SQL Server Performance Killers�������������������������������������������������������������������������������������������������� 15
Insufficient or Inaccurate Indexing���������������������������������������������������������������������������������������� 16
Inaccurate Statistics�������������������������������������������������������������������������������������������������������������� 17
Improper Query Design���������������������������������������������������������������������������������������������������������� 17
Poorly Generated Execution Plans����������������������������������������������������������������������������������������� 17
Excessive Blocking and Deadlocks��������������������������������������������������������������������������������������� 18
Non-Set-Based Operations���������������������������������������������������������������������������������������������������� 19
Inappropriate Database Design��������������������������������������������������������������������������������������������� 19
Recompiling Execution Plans������������������������������������������������������������������������������������������������ 20
Frequent Recompilation of Queries��������������������������������������������������������������������������������������� 20

v
Table of Contents

Improper Use of Cursors�������������������������������������������������������������������������������������������������������� 21


Excessive Index Fragmentation��������������������������������������������������������������������������������������������� 21
Summary������������������������������������������������������������������������������������������������������������������������������������ 21

Chapter 2: Memory Performance Analysis������������������������������������������������������������� 23


Performance Monitor Tool����������������������������������������������������������������������������������������������������������� 24
Dynamic Management Views������������������������������������������������������������������������������������������������������ 26
Hardware Resource Bottlenecks������������������������������������������������������������������������������������������������� 28
Identifying Bottlenecks���������������������������������������������������������������������������������������������������������� 28
Bottleneck Resolution������������������������������������������������������������������������������������������������������������ 29
Memory Bottleneck Analysis������������������������������������������������������������������������������������������������������� 30
SQL Server Memory Management���������������������������������������������������������������������������������������� 30
Available Bytes���������������������������������������������������������������������������������������������������������������������� 36
Pages/Sec and Page Faults/Sec�������������������������������������������������������������������������������������������� 36
Paging File %Usage and Page File %Usage�������������������������������������������������������������������������� 37
Buffer Cache Hit Ratio����������������������������������������������������������������������������������������������������������� 38
Page Life Expectancy������������������������������������������������������������������������������������������������������������ 38
Checkpoint Pages/Sec����������������������������������������������������������������������������������������������������������� 39
Lazy Writes/Sec��������������������������������������������������������������������������������������������������������������������� 39
Memory Grants Pending�������������������������������������������������������������������������������������������������������� 39
Target Server Memory (KB) and Total Server Memory (KB)��������������������������������������������������� 40
Additional Memory Monitoring Tools������������������������������������������������������������������������������������������� 40
DBCC MEMORYSTATUS���������������������������������������������������������������������������������������������������������� 41
Dynamic Management Views������������������������������������������������������������������������������������������������ 42
Monitoring Memory in Linux�������������������������������������������������������������������������������������������������� 45
Memory Bottleneck Resolutions������������������������������������������������������������������������������������������������� 45
Optimizing Application Workload������������������������������������������������������������������������������������������� 47
Allocating More Memory to SQL Server�������������������������������������������������������������������������������� 47
Moving In-Memory Tables Back to Standard Storage����������������������������������������������������������� 48
Increasing System Memory��������������������������������������������������������������������������������������������������� 48
Changing from a 32-Bit to a 64-Bit Processor���������������������������������������������������������������������� 48
Compressing Data����������������������������������������������������������������������������������������������������������������� 49

vi
Table of Contents

Enabling 3GB of Process Address Space������������������������������������������������������������������������������� 49


Addressing Fragmentation���������������������������������������������������������������������������������������������������� 50
Summary������������������������������������������������������������������������������������������������������������������������������������ 50

Chapter 3: Disk Performance Analysis������������������������������������������������������������������� 51


Disk Bottleneck Analysis������������������������������������������������������������������������������������������������������������� 51
Disk Counters������������������������������������������������������������������������������������������������������������������������ 52
Disk Transfers/Sec����������������������������������������������������������������������������������������������������������������� 54
Disk Bytes/Sec���������������������������������������������������������������������������������������������������������������������� 54
Avg. Disk Sec/Read and Avg. Disk Sec/Write������������������������������������������������������������������������ 55
Buffer Manager Page Reads/Writes�������������������������������������������������������������������������������������� 55
Additional I/O Monitoring Tools��������������������������������������������������������������������������������������������������� 55
Sys.dm_io_virtual_file_stats������������������������������������������������������������������������������������������������� 55
Sys.dm_os_wait_stats���������������������������������������������������������������������������������������������������������� 56
Monitoring Linux I/0�������������������������������������������������������������������������������������������������������������� 57
Disk Bottleneck Resolutions������������������������������������������������������������������������������������������������������� 57
Optimizing Application Workload������������������������������������������������������������������������������������������� 57
Using a Faster I/O Path���������������������������������������������������������������������������������������������������������� 58
Using a RAID Array����������������������������������������������������������������������������������������������������������������� 58
Using a SAN System�������������������������������������������������������������������������������������������������������������� 61
Using Solid-State Drives�������������������������������������������������������������������������������������������������������� 62
Aligning Disks Properly��������������������������������������������������������������������������������������������������������� 62
Adding System Memory�������������������������������������������������������������������������������������������������������� 62
Creating Multiple Files and Filegroups���������������������������������������������������������������������������������� 63
Moving the Log Files to a Separate Physical Disk����������������������������������������������������������������� 66
Using Partitioned Tables�������������������������������������������������������������������������������������������������������� 67
Summary������������������������������������������������������������������������������������������������������������������������������������ 68

Chapter 4: CPU Performance Analysis�������������������������������������������������������������������� 69


Processor Bottleneck Analysis���������������������������������������������������������������������������������������������������� 69
% Processor Time������������������������������������������������������������������������������������������������������������������ 71
% Privileged Time������������������������������������������������������������������������������������������������������������������ 72
Processor Queue Length������������������������������������������������������������������������������������������������������� 72

vii
Table of Contents

Context Switches/Sec������������������������������������������������������������������������������������������������������������ 72
Batch Requests/Sec�������������������������������������������������������������������������������������������������������������� 73
SQL Compilations/Sec����������������������������������������������������������������������������������������������������������� 73
SQL Recompilations/Sec������������������������������������������������������������������������������������������������������� 73
Other Tools for Measuring CPU Performance������������������������������������������������������������������������������ 74
Sys.dm_os_wait_stats���������������������������������������������������������������������������������������������������������� 74
Sys.dm_os_workers and Sys.dm_os_schedulers����������������������������������������������������������������� 74
Query Store���������������������������������������������������������������������������������������������������������������������������� 74
Measure CPU Behavior in Linux��������������������������������������������������������������������������������������������� 75
Processor Bottleneck Resolutions���������������������������������������������������������������������������������������������� 75
Optimizing Application Workload������������������������������������������������������������������������������������������� 75
Eliminating Excessive Compiles/Recompiles������������������������������������������������������������������������ 76
Using More or Faster Processors������������������������������������������������������������������������������������������ 76
Not Running Unnecessary Software�������������������������������������������������������������������������������������� 76
Network Bottleneck Analysis������������������������������������������������������������������������������������������������������ 77
Bytes Total/Sec���������������������������������������������������������������������������������������������������������������������� 77
% Net Utilization�������������������������������������������������������������������������������������������������������������������� 78
Network Bottleneck Resolutions������������������������������������������������������������������������������������������������� 78
Optimizing Application Workload������������������������������������������������������������������������������������������� 79
SQL Server Overall Performance������������������������������������������������������������������������������������������������ 79
Missing Indexes��������������������������������������������������������������������������������������������������������������������� 80
Database Concurrency���������������������������������������������������������������������������������������������������������� 82
Nonreusable Execution Plans������������������������������������������������������������������������������������������������ 83
General Behavior������������������������������������������������������������������������������������������������������������������� 84
User Connections������������������������������������������������������������������������������������������������������������������ 84
Batch Requests/Sec�������������������������������������������������������������������������������������������������������������� 84
Summary������������������������������������������������������������������������������������������������������������������������������������ 85

Chapter 5: Creating a Baseline������������������������������������������������������������������������������� 87


Considerations for Monitoring Virtual and Hosted Machines������������������������������������������������������ 87
Creating a Baseline��������������������������������������������������������������������������������������������������������������������� 89
Creating a Reusable List of Performance Counters��������������������������������������������������������������� 89

viii
Table of Contents

Creating a Counter Log Using the List of Performance Counters������������������������������������������ 92


Performance Monitor Considerations������������������������������������������������������������������������������������ 97
System Behavior Analysis Against Baseline�������������������������������������������������������������������������� 99
Baseline for Azure SQL Database��������������������������������������������������������������������������������������������� 102
Summary���������������������������������������������������������������������������������������������������������������������������������� 102

Chapter 6: Query Performance Metrics���������������������������������������������������������������� 103


Extended Events����������������������������������������������������������������������������������������������������������������������� 103
Extended Events Sessions��������������������������������������������������������������������������������������������������� 104
Global Fields������������������������������������������������������������������������������������������������������������������������ 111
Event Filters������������������������������������������������������������������������������������������������������������������������� 113
Event Fields������������������������������������������������������������������������������������������������������������������������� 116
Data Storage������������������������������������������������������������������������������������������������������������������������ 117
Finishing the Session���������������������������������������������������������������������������������������������������������� 119
The Built-in system_health Session������������������������������������������������������������������������������������ 121
Extended Events Automation���������������������������������������������������������������������������������������������������� 123
Creating a Session Script Using the GUI������������������������������������������������������������������������������ 123
Defining a Session Using T-SQL������������������������������������������������������������������������������������������� 124
Using Causality Tracking����������������������������������������������������������������������������������������������������������� 126
Extended Events Recommendations����������������������������������������������������������������������������������������� 127
Set Max File Size Appropriately������������������������������������������������������������������������������������������� 127
Be Cautious with Debug Events������������������������������������������������������������������������������������������� 128
Avoid Use of No_Event_Loss����������������������������������������������������������������������������������������������� 128
Other Methods for Query Performance Metrics������������������������������������������������������������������������ 128
Summary���������������������������������������������������������������������������������������������������������������������������������� 130

Chapter 7: Analyzing Query Performance������������������������������������������������������������� 131


Costly Queries��������������������������������������������������������������������������������������������������������������������������� 131
Identifying Costly Queries���������������������������������������������������������������������������������������������������� 133
Costly Queries with a Single Execution������������������������������������������������������������������������������� 135
Costly Queries with Multiple Executions����������������������������������������������������������������������������� 137
Identifying Slow-Running Queries��������������������������������������������������������������������������������������� 141

ix
Table of Contents

Execution Plans������������������������������������������������������������������������������������������������������������������������� 142


Analyzing a Query Execution Plan��������������������������������������������������������������������������������������� 144
Identifying the Costly Steps in an Execution Plan��������������������������������������������������������������� 148
Analyzing Index Effectiveness��������������������������������������������������������������������������������������������� 150
Analyzing Join Effectiveness����������������������������������������������������������������������������������������������� 153
Actual vs. Estimated Execution Plans���������������������������������������������������������������������������������� 161
Plan Cache��������������������������������������������������������������������������������������������������������������������������� 164
Execution Plan Tooling��������������������������������������������������������������������������������������������������������� 164
Query Resource Cost����������������������������������������������������������������������������������������������������������������� 176
Client Statistics������������������������������������������������������������������������������������������������������������������� 176
Execution Time�������������������������������������������������������������������������������������������������������������������� 178
STATISTICS IO���������������������������������������������������������������������������������������������������������������������� 179
Actual Execution Plans�������������������������������������������������������������������������������������������������������� 181
Summary���������������������������������������������������������������������������������������������������������������������������������� 182

Chapter 8: Index Architecture and Behavior�������������������������������������������������������� 185


What Is an Index?���������������������������������������������������������������������������������������������������������������������� 185
The Benefit of Indexes��������������������������������������������������������������������������������������������������������� 188
Index Overhead�������������������������������������������������������������������������������������������������������������������� 191
Index Design Recommendations����������������������������������������������������������������������������������������������� 194
Examine the WHERE Clause and JOIN Criteria Columns����������������������������������������������������� 195
Use Narrow Indexes������������������������������������������������������������������������������������������������������������ 197
Examine Column Uniqueness���������������������������������������������������������������������������������������������� 200
Examine the Column Data Type������������������������������������������������������������������������������������������� 204
Consider Index Column Order���������������������������������������������������������������������������������������������� 205
Consider the Type of Index�������������������������������������������������������������������������������������������������� 208
Clustered Indexes��������������������������������������������������������������������������������������������������������������������� 209
Heap Tables������������������������������������������������������������������������������������������������������������������������� 209
Relationship with Nonclustered Indexes����������������������������������������������������������������������������� 209
Clustered Index Recommendations������������������������������������������������������������������������������������� 213
When to Use a Clustered Index�������������������������������������������������������������������������������������������� 217
Poor Design Practices for a Clustered Index����������������������������������������������������������������������� 219

x
Table of Contents

Nonclustered Indexes��������������������������������������������������������������������������������������������������������������� 221


Nonclustered Index Maintenance���������������������������������������������������������������������������������������� 221
Defining the Lookup Operation�������������������������������������������������������������������������������������������� 222
Nonclustered Index Recommendations������������������������������������������������������������������������������� 223
Clustered vs. Nonclustered Indexes������������������������������������������������������������������������������������������ 224
Benefits of a Clustered Index over a Nonclustered Index���������������������������������������������������� 224
Benefits of a Nonclustered Index over a Clustered Index���������������������������������������������������� 227
Summary���������������������������������������������������������������������������������������������������������������������������������� 230

Chapter 9: Index Analysis������������������������������������������������������������������������������������� 231


Advanced Indexing Techniques������������������������������������������������������������������������������������������������� 231
Covering Indexes����������������������������������������������������������������������������������������������������������������� 232
A Pseudoclustered Index����������������������������������������������������������������������������������������������������� 234
Recommendations��������������������������������������������������������������������������������������������������������������� 235
Index Intersections�������������������������������������������������������������������������������������������������������������� 235
Index Joins�������������������������������������������������������������������������������������������������������������������������� 238
Filtered Indexes������������������������������������������������������������������������������������������������������������������� 242
Indexed Views���������������������������������������������������������������������������������������������������������������������� 246
Index Compression�������������������������������������������������������������������������������������������������������������� 253
Columnstore Indexes���������������������������������������������������������������������������������������������������������������� 256
Columnstore Index Storage������������������������������������������������������������������������������������������������� 257
Columnstore Index Behavior������������������������������������������������������������������������������������������������ 258
Recommendations��������������������������������������������������������������������������������������������������������������� 266
Special Index Types������������������������������������������������������������������������������������������������������������������� 266
Full-Text������������������������������������������������������������������������������������������������������������������������������� 267
Spatial��������������������������������������������������������������������������������������������������������������������������������� 267
XML������������������������������������������������������������������������������������������������������������������������������������� 268
Additional Characteristics of Indexes���������������������������������������������������������������������������������������� 268
Different Column Sort Order������������������������������������������������������������������������������������������������ 268
Index on Computed Columns����������������������������������������������������������������������������������������������� 268
Index on BIT Data Type Columns����������������������������������������������������������������������������������������� 269

xi
Table of Contents

CREATE INDEX Statement Processed As a Query���������������������������������������������������������������� 269


Parallel Index Creation��������������������������������������������������������������������������������������������������������� 270
Online Index Creation���������������������������������������������������������������������������������������������������������� 270
Considering the Database Engine Tuning Advisor��������������������������������������������������������������� 271
Summary���������������������������������������������������������������������������������������������������������������������������������� 271

Chapter 10: Database Engine Tuning Advisor������������������������������������������������������� 273


Database Engine Tuning Advisor Mechanisms�������������������������������������������������������������������������� 273
Database Engine Tuning Advisor Examples������������������������������������������������������������������������������ 279
Tuning a Query��������������������������������������������������������������������������������������������������������������������� 279
Tuning a Trace Workload����������������������������������������������������������������������������������������������������� 285
Tuning from the Procedure Cache��������������������������������������������������������������������������������������� 288
Tuning from the Query Store����������������������������������������������������������������������������������������������� 289
Database Engine Tuning Advisor Limitations���������������������������������������������������������������������������� 290
Summary���������������������������������������������������������������������������������������������������������������������������������� 291

Chapter 11: Query Store��������������������������������������������������������������������������������������� 293


Query Store Function and Design��������������������������������������������������������������������������������������������� 293
Query Store Behavior����������������������������������������������������������������������������������������������������������� 294
Information Query Store Collects���������������������������������������������������������������������������������������� 297
Controlling the Query Store������������������������������������������������������������������������������������������������� 306
Query Store Reporting��������������������������������������������������������������������������������������������������������������� 309
Plan Forcing������������������������������������������������������������������������������������������������������������������������������ 313
Query Store for Upgrades��������������������������������������������������������������������������������������������������������� 316
Summary���������������������������������������������������������������������������������������������������������������������������������� 317

Chapter 12: Key Lookups and Solutions��������������������������������������������������������������� 319


Purpose of Lookups������������������������������������������������������������������������������������������������������������������ 319
Drawbacks of Lookups�������������������������������������������������������������������������������������������������������������� 322
Analyzing the Cause of a Lookup���������������������������������������������������������������������������������������������� 323
Resolving Lookups�������������������������������������������������������������������������������������������������������������������� 326
Using a Clustered Index������������������������������������������������������������������������������������������������������� 326

xii
Table of Contents

Using a Covering Index�������������������������������������������������������������������������������������������������������� 327


Using an Index Join������������������������������������������������������������������������������������������������������������� 333
Summary���������������������������������������������������������������������������������������������������������������������������������� 335

Chapter 13: Statistics, Data Distribution, and Cardinality������������������������������������ 337


The Role of Statistics in Query Optimization����������������������������������������������������������������������������� 338
Statistics on an Indexed Column����������������������������������������������������������������������������������������� 338
Benefits of Updated Statistics��������������������������������������������������������������������������������������������� 339
Drawbacks of Outdated Statistics��������������������������������������������������������������������������������������� 345
Statistics on a Nonindexed Column������������������������������������������������������������������������������������������ 347
Benefits of Statistics on a Nonindexed Column������������������������������������������������������������������� 348
Drawback of Missing Statistics on a Nonindexed Column�������������������������������������������������� 355
Analyzing Statistics������������������������������������������������������������������������������������������������������������������� 359
Density��������������������������������������������������������������������������������������������������������������������������������� 363
Statistics on a Multicolumn Index��������������������������������������������������������������������������������������� 364
Statistics on a Filtered Index����������������������������������������������������������������������������������������������� 367
Cardinality��������������������������������������������������������������������������������������������������������������������������� 370
Statistics DMOs������������������������������������������������������������������������������������������������������������������� 379
Statistics Maintenance������������������������������������������������������������������������������������������������������������� 380
Automatic Maintenance������������������������������������������������������������������������������������������������������� 381
Auto Create Statistics���������������������������������������������������������������������������������������������������������� 381
Auto Update Statistics��������������������������������������������������������������������������������������������������������� 382
Auto Update Statistics Asynchronously������������������������������������������������������������������������������� 385
Manual Maintenance����������������������������������������������������������������������������������������������������������� 385
Manage Statistics Settings�������������������������������������������������������������������������������������������������� 387
Generate Statistics�������������������������������������������������������������������������������������������������������������� 388
Statistics Maintenance Status�������������������������������������������������������������������������������������������������� 390
Status of Auto Create Statistics������������������������������������������������������������������������������������������� 390
Analyzing the Effectiveness of Statistics for a Query��������������������������������������������������������������� 391
Resolving a Missing Statistics Issue����������������������������������������������������������������������������������� 392
Resolving an Outdated Statistics Issue������������������������������������������������������������������������������� 396

xiii
Table of Contents

Recommendations�������������������������������������������������������������������������������������������������������������������� 400
Backward Compatibility of Statistics����������������������������������������������������������������������������������� 400
Auto Create Statistics���������������������������������������������������������������������������������������������������������� 401
Auto Update Statistics��������������������������������������������������������������������������������������������������������� 401
Automatic Update Statistics Asynchronously���������������������������������������������������������������������� 401
Amount of Sampling to Collect Statistics���������������������������������������������������������������������������� 402
Summary���������������������������������������������������������������������������������������������������������������������������������� 402

Chapter 14: Index Fragmentation������������������������������������������������������������������������� 403


Discussion on Fragmentation��������������������������������������������������������������������������������������������������� 404
Causes of Fragmentation���������������������������������������������������������������������������������������������������������� 405
Data Modification and the Rowstore Indexes���������������������������������������������������������������������� 405
Data Modification and the Columnstore Indexes����������������������������������������������������������������� 415
Fragmentation Overhead���������������������������������������������������������������������������������������������������������� 418
Rowstore Overhead������������������������������������������������������������������������������������������������������������� 418
Columnstore Overhead�������������������������������������������������������������������������������������������������������� 421
Analyzing the Amount of Fragmentation����������������������������������������������������������������������������������� 423
Analyzing the Fragmentation of a Small Table�������������������������������������������������������������������������� 428
Fragmentation Resolutions������������������������������������������������������������������������������������������������������� 430
Dropping and Re-creating the Index������������������������������������������������������������������������������������ 431
Re-creating the Index with the DROP_EXISTING Clause������������������������������������������������������ 432
Executing the ALTER INDEX REBUILD Statement����������������������������������������������������������������� 433
Executing the ALTER INDEX REORGANIZE Statement���������������������������������������������������������� 437
Defragmentation and Partitions������������������������������������������������������������������������������������������� 444
Significance of the Fill Factor��������������������������������������������������������������������������������������������������� 445
Automatic Maintenance������������������������������������������������������������������������������������������������������������ 449
Summary���������������������������������������������������������������������������������������������������������������������������������� 450

Chapter 15: Execution Plan Generation���������������������������������������������������������������� 451


Execution Plan Generation�������������������������������������������������������������������������������������������������������� 451
Parser���������������������������������������������������������������������������������������������������������������������������������� 454
Binding�������������������������������������������������������������������������������������������������������������������������������� 454

xiv
Table of Contents

Optimization������������������������������������������������������������������������������������������������������������������������ 457
Execution Plan Caching������������������������������������������������������������������������������������������������������� 468
Components of the Execution Plan������������������������������������������������������������������������������������������� 468
Query Plan��������������������������������������������������������������������������������������������������������������������������� 468
Execution Context���������������������������������������������������������������������������������������������������������������� 469
Aging of the Execution Plan������������������������������������������������������������������������������������������������������ 469
Summary���������������������������������������������������������������������������������������������������������������������������������� 470

Chapter 16: Execution Plan Cache Behavior��������������������������������������������������������� 471


Analyzing the Execution Plan Cache����������������������������������������������������������������������������������������� 471
Execution Plan Reuse���������������������������������������������������������������������������������������������������������������� 473
Ad Hoc Workload����������������������������������������������������������������������������������������������������������������������� 474
Prepared Workload�������������������������������������������������������������������������������������������������������������� 475
Plan Reusability of an Ad Hoc Workload������������������������������������������������������������������������������ 476
Plan Reusability of a Prepared Workload����������������������������������������������������������������������������� 488
Query Plan Hash and Query Hash��������������������������������������������������������������������������������������������� 499
Execution Plan Cache Recommendations��������������������������������������������������������������������������������� 504
Explicitly Parameterize Variable Parts of a Query���������������������������������������������������������������� 504
Create Stored Procedures to Implement Business Functionality���������������������������������������� 505
Code with sp_executesql to Avoid Stored Procedure Deployment�������������������������������������� 505
Implement the Prepare/Execute Model to Avoid Resending a Query String������������������������ 506
Avoid Ad Hoc Queries���������������������������������������������������������������������������������������������������������� 506
Prefer sp_executesql Over EXECUTE for Dynamic Queries������������������������������������������������� 506
Parameterize Variable Parts of Queries with Care��������������������������������������������������������������� 508
Do Not Allow Implicit Resolution of Objects in Queries������������������������������������������������������� 508
Summary���������������������������������������������������������������������������������������������������������������������������������� 509

Chapter 17: Parameter Sniffing���������������������������������������������������������������������������� 511


Parameter Sniffing�������������������������������������������������������������������������������������������������������������������� 511
Bad Parameter Sniffing������������������������������������������������������������������������������������������������������������� 515
Identifying Bad Parameter Sniffing������������������������������������������������������������������������������������� 518
Mitigating Bad Parameter Sniffing�������������������������������������������������������������������������������������� 521
Summary���������������������������������������������������������������������������������������������������������������������������������� 528
xv
Table of Contents

Chapter 18: Query Recompilation������������������������������������������������������������������������� 529


Benefits and Drawbacks of Recompilation������������������������������������������������������������������������������� 529
Identifying the Statement Causing Recompilation�������������������������������������������������������������������� 533
Analyzing Causes of Recompilation������������������������������������������������������������������������������������������ 535
Schema or Bindings Changes���������������������������������������������������������������������������������������������� 536
Statistics Changes��������������������������������������������������������������������������������������������������������������� 536
Deferred Object Resolution�������������������������������������������������������������������������������������������������� 540
SET Options Changes���������������������������������������������������������������������������������������������������������� 544
Execution Plan Aging����������������������������������������������������������������������������������������������������������� 545
Explicit Call to sp_recompile����������������������������������������������������������������������������������������������� 545
Explicit Use of RECOMPILE�������������������������������������������������������������������������������������������������� 547
Avoiding Recompilations����������������������������������������������������������������������������������������������������������� 550
Don’t Interleave DDL and DML Statements������������������������������������������������������������������������� 551
Avoiding Recompilations Caused by Statistics Change������������������������������������������������������� 553
Using the KEEPFIXED PLAN Option�������������������������������������������������������������������������������������� 554
Disable Auto Update Statistics on the Table������������������������������������������������������������������������ 556
Using Table Variables����������������������������������������������������������������������������������������������������������� 556
Avoiding Changing SET Options Within a Stored Procedure������������������������������������������������ 558
Using OPTIMIZE FOR Query Hint������������������������������������������������������������������������������������������ 559
Using Plan Guides���������������������������������������������������������������������������������������������������������������� 561
Use Query Store to Force a Plan������������������������������������������������������������������������������������������ 567
Summary���������������������������������������������������������������������������������������������������������������������������������� 567

Chapter 19: Query Design Analysis���������������������������������������������������������������������� 569


Query Design Recommendations���������������������������������������������������������������������������������������������� 569
Operating on Small Result Sets������������������������������������������������������������������������������������������������ 570
Limit the Number of Columns in select_list������������������������������������������������������������������������ 571
Use Highly Selective WHERE Clauses���������������������������������������������������������������������������������� 572
Using Indexes Effectively���������������������������������������������������������������������������������������������������������� 573
Avoid Nonsargable Search Conditions��������������������������������������������������������������������������������� 573
Avoid Arithmetic Operators on the WHERE Clause Column������������������������������������������������� 580
Avoid Functions on the WHERE Clause Column������������������������������������������������������������������� 582

xvi
Table of Contents

Minimize Optimizer Hints���������������������������������������������������������������������������������������������������������� 589


JOIN Hint������������������������������������������������������������������������������������������������������������������������������ 590
INDEX Hints�������������������������������������������������������������������������������������������������������������������������� 595
Using Domain and Referential Integrity������������������������������������������������������������������������������������ 597
NOT NULL Constraint����������������������������������������������������������������������������������������������������������� 597
Declarative Referential Integrity������������������������������������������������������������������������������������������ 600
Summary���������������������������������������������������������������������������������������������������������������������������������� 605

Chapter 20: Reduce Query Resource Use������������������������������������������������������������� 607


Avoiding Resource-Intensive Queries��������������������������������������������������������������������������������������� 607
Avoid Data Type Conversion������������������������������������������������������������������������������������������������ 608
Use EXISTS over COUNT(*) to Verify Data Existence������������������������������������������������������������ 611
Use UNION ALL Instead of UNION���������������������������������������������������������������������������������������� 612
Use Indexes for Aggregate and Sort Conditions������������������������������������������������������������������ 614
Be Cautious with Local Variables in a Batch Query������������������������������������������������������������� 616
Be Careful When Naming Stored Procedures���������������������������������������������������������������������� 621
Reducing the Number of Network Round-Trips������������������������������������������������������������������������ 623
Execute Multiple Queries Together�������������������������������������������������������������������������������������� 624
Use SET NOCOUNT��������������������������������������������������������������������������������������������������������������� 624
Reducing the Transaction Cost������������������������������������������������������������������������������������������������� 624
Reduce Logging Overhead��������������������������������������������������������������������������������������������������� 625
Reduce Lock Overhead�������������������������������������������������������������������������������������������������������� 627
Summary���������������������������������������������������������������������������������������������������������������������������������� 629

Chapter 21: Blocking and Blocked Processes������������������������������������������������������ 631


Blocking Fundamentals������������������������������������������������������������������������������������������������������������ 632
Understanding Blocking������������������������������������������������������������������������������������������������������������ 633
Atomicity����������������������������������������������������������������������������������������������������������������������������� 633
Consistency������������������������������������������������������������������������������������������������������������������������� 637
Isolation������������������������������������������������������������������������������������������������������������������������������� 638
Durability����������������������������������������������������������������������������������������������������������������������������� 639

xvii
Table of Contents

Locks����������������������������������������������������������������������������������������������������������������������������������������� 641
Lock Granularity������������������������������������������������������������������������������������������������������������������ 641
Row-Level Lock������������������������������������������������������������������������������������������������������������������� 642
Key-Level Lock�������������������������������������������������������������������������������������������������������������������� 643
Page-Level Lock������������������������������������������������������������������������������������������������������������������ 645
Extent-Level Lock���������������������������������������������������������������������������������������������������������������� 645
Heap or B-tree Lock������������������������������������������������������������������������������������������������������������ 645
Table-Level Lock������������������������������������������������������������������������������������������������������������������ 646
Database-Level Lock����������������������������������������������������������������������������������������������������������� 647
Lock Operations and Modes������������������������������������������������������������������������������������������������������ 647
Lock Escalation������������������������������������������������������������������������������������������������������������������� 647
Lock Modes������������������������������������������������������������������������������������������������������������������������� 648
Exclusive (X) Mode�������������������������������������������������������������������������������������������������������������� 656
Intent Shared (IS), Intent Exclusive (IX), and Shared with Intent Exclusive (SIX) Modes����� 657
Schema Modification (Sch-M) and Schema Stability (Sch-­S) Modes���������������������������������� 658
Bulk Update (BU) Mode�������������������������������������������������������������������������������������������������������� 658
Key-Range Mode����������������������������������������������������������������������������������������������������������������� 659
Lock Compatibility��������������������������������������������������������������������������������������������������������������� 659
Isolation Levels������������������������������������������������������������������������������������������������������������������������� 659
Read Uncommitted�������������������������������������������������������������������������������������������������������������� 660
Read Committed������������������������������������������������������������������������������������������������������������������ 661
Repeatable Read����������������������������������������������������������������������������������������������������������������� 663
Serializable�������������������������������������������������������������������������������������������������������������������������� 667
Snapshot����������������������������������������������������������������������������������������������������������������������������� 674
Effect of Indexes on Locking����������������������������������������������������������������������������������������������������� 675
Effect of a Nonclustered Index�������������������������������������������������������������������������������������������� 676
Effect of a Clustered Index�������������������������������������������������������������������������������������������������� 678
Effect of Indexes on the Serializable Isolation Level����������������������������������������������������������� 679
Capturing Blocking Information������������������������������������������������������������������������������������������������ 680
Capturing Blocking Information with SQL��������������������������������������������������������������������������� 681
Extended Events and the blocked_process_report Event��������������������������������������������������� 684

xviii
Table of Contents

Blocking Resolutions����������������������������������������������������������������������������������������������������������������� 688


Optimize the Queries����������������������������������������������������������������������������������������������������������� 688
Decrease the Isolation Level����������������������������������������������������������������������������������������������� 690
Partition the Contended Data���������������������������������������������������������������������������������������������������� 690
Recommendations to Reduce Blocking������������������������������������������������������������������������������������ 692
Automation to Detect and Collect Blocking Information����������������������������������������������������������� 693
Summary���������������������������������������������������������������������������������������������������������������������������������� 698

Chapter 22: Causes and Solutions for Deadlocks������������������������������������������������� 699


Deadlock Fundamentals����������������������������������������������������������������������������������������������������������� 699
Choosing the Deadlock Victim��������������������������������������������������������������������������������������������� 701
Using Error Handling to Catch a Deadlock��������������������������������������������������������������������������� 702
Deadlock Analysis��������������������������������������������������������������������������������������������������������������������� 703
Collecting Deadlock Information����������������������������������������������������������������������������������������� 703
Analyzing the Deadlock������������������������������������������������������������������������������������������������������� 707
Avoiding Deadlocks������������������������������������������������������������������������������������������������������������������� 715
Accessing Resources in the Same Physical Order�������������������������������������������������������������� 715
Decreasing the Number of Resources Accessed����������������������������������������������������������������� 716
Minimizing Lock Contention������������������������������������������������������������������������������������������������ 717
Summary���������������������������������������������������������������������������������������������������������������������������������� 719

Chapter 23: Row-by-Row Processing������������������������������������������������������������������� 721


Cursor Fundamentals���������������������������������������������������������������������������������������������������������������� 721
Cursor Location������������������������������������������������������������������������������������������������������������������� 724
Cursor Concurrency������������������������������������������������������������������������������������������������������������� 725
Cursor Types������������������������������������������������������������������������������������������������������������������������ 727
Cursor Cost Comparison����������������������������������������������������������������������������������������������������������� 731
Cost Comparison on Cursor Location���������������������������������������������������������������������������������� 731
Cost Comparison on Cursor Concurrency���������������������������������������������������������������������������� 734
Cost Comparison on Cursor Type����������������������������������������������������������������������������������������� 737

xix
Table of Contents

Default Result Set��������������������������������������������������������������������������������������������������������������������� 741


Benefits������������������������������������������������������������������������������������������������������������������������������� 742
Multiple Active Result Sets�������������������������������������������������������������������������������������������������� 742
Drawbacks��������������������������������������������������������������������������������������������������������������������������� 743
Cursor Overhead����������������������������������������������������������������������������������������������������������������������� 746
Analyzing Overhead with T-SQL Cursors����������������������������������������������������������������������������� 746
Cursor Recommendations��������������������������������������������������������������������������������������������������� 751
Summary���������������������������������������������������������������������������������������������������������������������������������� 752

Chapter 24: Memory-Optimized OLTP Tables and Procedures������������������������������ 753


In-Memory OLTP Fundamentals������������������������������������������������������������������������������������������������ 754
System Requirements��������������������������������������������������������������������������������������������������������� 755
Basic Setup������������������������������������������������������������������������������������������������������������������������� 756
Create Tables����������������������������������������������������������������������������������������������������������������������� 757
In-Memory Indexes�������������������������������������������������������������������������������������������������������������� 763
Natively Compiled Stored Procedures��������������������������������������������������������������������������������������� 771
Recommendations�������������������������������������������������������������������������������������������������������������������� 774
Baselines����������������������������������������������������������������������������������������������������������������������������� 774
Correct Workload����������������������������������������������������������������������������������������������������������������� 774
Memory Optimization Advisor���������������������������������������������������������������������������������������������� 774
Native Compilation Advisor�������������������������������������������������������������������������������������������������� 779
Summary���������������������������������������������������������������������������������������������������������������������������������� 781

Chapter 25: Automated Tuning in Azure SQL Database and SQL Server��������������� 783
Automatic Plan Correction�������������������������������������������������������������������������������������������������������� 784
Tuning Recommendations��������������������������������������������������������������������������������������������������� 785
Enabling Automatic Tuning�������������������������������������������������������������������������������������������������� 792
Azure SQL Database Automatic Index Management����������������������������������������������������������������� 799
Adaptive Query Processing������������������������������������������������������������������������������������������������������� 810
Batch Mode Memory Grant Feedback��������������������������������������������������������������������������������� 810
Interleaved Execution���������������������������������������������������������������������������������������������������������� 815
Summary���������������������������������������������������������������������������������������������������������������������������������� 823

xx
Table of Contents

Chapter 26: Database Performance Testing��������������������������������������������������������� 825


Database Performance Testing������������������������������������������������������������������������������������������������� 826
A Repeatable Process���������������������������������������������������������������������������������������������������������� 827
Distributed Replay��������������������������������������������������������������������������������������������������������������� 828
Capturing Data with the Server-Side Trace������������������������������������������������������������������������������� 829
Distributed Replay for Database Testing����������������������������������������������������������������������������������� 833
Configuring the Client���������������������������������������������������������������������������������������������������������� 835
Running the Distributed Tests���������������������������������������������������������������������������������������������� 836
Conclusion�������������������������������������������������������������������������������������������������������������������������������� 837

Chapter 27: Database Workload Optimization������������������������������������������������������ 839


Workload Optimization Fundamentals�������������������������������������������������������������������������������������� 840
Workload Optimization Steps���������������������������������������������������������������������������������������������� 840
Sample Workload����������������������������������������������������������������������������������������������������������������� 842
Capturing the Workload������������������������������������������������������������������������������������������������������������ 847
Analyzing the Workload������������������������������������������������������������������������������������������������������������ 848
Identifying the Costliest Query�������������������������������������������������������������������������������������������������� 851
Determining the Baseline Resource Use of the Costliest Query����������������������������������������� 852
Overall Resource Use���������������������������������������������������������������������������������������������������������� 853
Detailed Resource Use�������������������������������������������������������������������������������������������������������� 854
Analyzing and Optimizing External Factors������������������������������������������������������������������������������� 857
Analyzing the Connection Options Used by the Application������������������������������������������������ 857
Analyzing the Effectiveness of Statistics����������������������������������������������������������������������������� 858
Analyzing the Need for Defragmentation���������������������������������������������������������������������������� 861
Analyzing the Internal Behavior of the Costliest Query������������������������������������������������������������� 864
Analyzing the Query Execution Plan������������������������������������������������������������������������������������ 864
Identifying the Costly Steps in the Execution Plan�������������������������������������������������������������� 866
Analyzing the Processing Strategy�������������������������������������������������������������������������������������� 867
Optimizing the Costliest Query�������������������������������������������������������������������������������������������������� 867
Modifying the Code�������������������������������������������������������������������������������������������������������������� 868
Fixing the Key Lookup Operation����������������������������������������������������������������������������������������� 871

xxi
Table of Contents

Tuning the Second Query���������������������������������������������������������������������������������������������������� 872


Creating a Wrapper Procedure�������������������������������������������������������������������������������������������� 874
Analyzing the Effect on Database Workload����������������������������������������������������������������������������� 877
Iterating Through Optimization Phases������������������������������������������������������������������������������������� 878
Summary���������������������������������������������������������������������������������������������������������������������������������� 881

Chapter 28: SQL Server Optimization Checklist��������������������������������������������������� 883


Database Design����������������������������������������������������������������������������������������������������������������������� 884
Use Entity-Integrity Constraints������������������������������������������������������������������������������������������� 884
Maintain Domain and Referential Integrity Constraints������������������������������������������������������� 887
Adopt Index-Design Best Practices������������������������������������������������������������������������������������� 890
Avoid the Use of the sp_Prefix for Stored Procedure Names���������������������������������������������� 892
Minimize the Use of Triggers����������������������������������������������������������������������������������������������� 892
Put Tables into In-Memory Storage������������������������������������������������������������������������������������� 892
Use Columnstore Indexes���������������������������������������������������������������������������������������������������� 893
Configuration Settings�������������������������������������������������������������������������������������������������������������� 893
Memory Configuration Options�������������������������������������������������������������������������������������������� 894
Cost Threshold for Parallelism��������������������������������������������������������������������������������������������� 894
Max Degree of Parallelism�������������������������������������������������������������������������������������������������� 894
Optimize for Ad Hoc Workloads������������������������������������������������������������������������������������������� 895
Blocked Process Threshold������������������������������������������������������������������������������������������������� 895
Database File Layout����������������������������������������������������������������������������������������������������������� 895
Database Compression�������������������������������������������������������������������������������������������������������� 896
Database Administration����������������������������������������������������������������������������������������������������������� 896
Keep the Statistics Up-to-Date�������������������������������������������������������������������������������������������� 897
Maintain a Minimum Amount of Index Defragmentation����������������������������������������������������� 898
Avoid Database Functions Such As AUTO_CLOSE or AUTO_SHRINK����������������������������������� 898
Database Backup���������������������������������������������������������������������������������������������������������������������� 899
Incremental and Transaction Log Backup Frequency���������������������������������������������������������� 899
Backup Scheduling Distribution������������������������������������������������������������������������������������������ 900
Backup Compression����������������������������������������������������������������������������������������������������������� 901

xxii
Table of Contents

Query Design����������������������������������������������������������������������������������������������������������������������������� 901


Use the Command SET NOCOUNT ON���������������������������������������������������������������������������������� 902
Explicitly Define the Owner of an Object����������������������������������������������������������������������������� 902
Avoid Nonsargable Search Conditions��������������������������������������������������������������������������������� 902
Avoid Arithmetic Expressions on the WHERE Clause Column���������������������������������������������� 903
Avoid Optimizer Hints���������������������������������������������������������������������������������������������������������� 904
Stay Away from Nesting Views�������������������������������������������������������������������������������������������� 905
Ensure No Implicit Data Type Conversions�������������������������������������������������������������������������� 905
Minimize Logging Overhead������������������������������������������������������������������������������������������������ 905
Adopt Best Practices for Reusing Execution Plans�������������������������������������������������������������� 906
Adopt Best Practices for Database Transactions����������������������������������������������������������������� 907
Eliminate or Reduce the Overhead of Database Cursors����������������������������������������������������� 908
Use Natively Compile Stored Procedures���������������������������������������������������������������������������� 909
Take Advantage of Query Store for Analytical Queries�������������������������������������������������������� 909
Summary���������������������������������������������������������������������������������������������������������������������������������� 909

Index��������������������������������������������������������������������������������������������������������������������� 911

xxiii
About the Author
Grant Fritchey, Microsoft Data Platform MVP, has more than 20 years of experience
in IT. That time was spent in technical support, development, and database
administration. He currently works as a product evangelist at Red Gate Software.
Grant writes articles for publication at SQL Server Central and Simple-Talk. He has
published books, including SQL Server Execution Plans and SQL Server 2012 Query
Performance Tuning (Apress). He has written chapters for Beginning SQL Server 2012
Administration (Apress), SQL Server Team-based Development, SQL Server MVP Deep
Dives Volume 2, Pro SQL Server 2012 Practices (Apress), and Expert Performance Indexing
in SQL Server (Apress). Grant currently serves as the president on the board of directors
of the PASS organization, the leading source of educational content and training on the
Microsoft data platform.

xxv
About the Technical Reviewer
Joseph Sack is a principal program manager at Microsoft,
focusing on query processing for Azure SQL Database and
SQL Server. He has worked as a SQL Server professional
since 1997 and has supported and developed for SQL
Server environments in financial services, IT consulting,
manufacturing, retail, and the real estate industry.
Joe joined Microsoft in 2006 and was a SQL Server
premier field engineer for large retail customers in
Minneapolis, Minnesota. He was responsible for
providing deep SQL Server advisory services, training,
troubleshooting, and ongoing solutions guidance. In 2006
Joe earned the Microsoft Certified Master: SQL Server 2005
certification, and in 2008 he earned the Microsoft Certified
Master: SQL Server 2008 certification. In 2009 he took over
responsibility for the entire SQL Server Microsoft Certified Master program and held that
post until 2011.
He left Microsoft in late 2011 to join SQLskills, working as a principal consultant.
During that time, he co-instructed for various training events and was a consultant
for customer performance tuning engagements. He recorded 13 Pluralsight courses,
including SQL Server: Troubleshooting Query Plan Quality Issues, SQL Server: Transact-­
SQL Basic Data Retrieval, and SQL Server: Common Query Tuning Problems and
Solutions. He returned to Microsoft in 2015.
Over the years Joe has published and edited several SQL Server books and
white papers. His first book, SQL Server 2000 Fast Answers for DBAs and Developers,
was published in 2003. He also started and maintained the T-SQL Recipe series,
including SQL Server 2005 T-SQL Recipes and SQL Server 2008 Transact-SQL Recipes.
His most popular white papers include “Optimizing Your Query Plans with the SQL
Server 2014 Cardinality Estimator” and “AlwaysOn Architecture Guide: Building a High
Availability and Disaster Recovery Solution by Using Failover Cluster Instances and

xxvii
About the Technical Reviewer

Availability Groups.” Currently he writes (along with his colleagues) on the SQL Server
Engine Blog. His classic posts can still be found at https://www.sqlskills.com/blogs/
joe/ and https://blogs.msdn.microsoft.com/joesack/.
His Twitter handle is @JoeSackMSFT, and you can find Joe speaking at most major
SQL Server conferences. He spends half his time between Minneapolis and Seattle,
meaning that he is either cold or wet at any given point in time.

xxviii
Acknowledgments
The poor editors at Apress have to put up with me and my bad scheduling, so first and
foremost, thanks to Jill Balzano and Jonathan Gennick. To say I couldn’t have done it
without you doesn’t begin to cover it. I’ve said it before and I’ll say it again here, publicly
and forever in print, Joe Sack is my hero. Thanks for everything, Joe.

xxix
Introduction
Technology is changing all the time, faster and faster. New functionality is introduced
in Azure SQL Database on an almost weekly schedule, and SQL Server itself has gone
through two releases since the last edition of this book was published. New styles of
databases are introduced all the time. With all this change, the question immediately in
front of you should be, do we still need to do query tuning?
The answer is a very short and resounding, yes.
With all the functionality and capability built into SQL Server and the Azure Data
Platform, not only is query tuning still an important skill, it actually becomes a way to
save your organization money. Knowing how to make a query run faster so that fewer
resources are needed literally becomes a way to reduce costs within a platform-as-a-­
service offering such as Azure SQL Database.
However, it’s not just about money. The code generated by object-relational mapping
tools such as Entity Framework can be fantastic, until it isn’t. Then, you’ll be working on
creating custom scripts and generating data structures and indexes and all the rest of
traditional query performance tuning.
While technology has certainly moved fast and far, there is still a fundamental need
to get queries to run faster and do more with less overhead on your servers. That’s where
this book comes into play. This is a resource that you can use to ensure that you’re using
all the tools in your hands to ensure that the databases you build, develop, and maintain
will continue to run faster.

Who Is This Book For?


If you write or generate T-SQL, you’re going to need to make it run faster. So, this book is
for data analysts, developers, coders, database designers, database developers, and that
last bastion of protection for the company’s information, the database administrator.
You’ll all need at one point or another to understand how indexes work, where to track
down performance metrics, and methods and mechanisms to ensure that your queries
run as fast as they can.
The code for the book is available from Apress.com. If you have questions, want
suggestions, or just need a little help, you can get in touch with me at ­[email protected].
xxxi
CHAPTER 1

SQL Query Performance


Tuning
Query performance tuning continues to be a fundamental aspect of modern database
maintenance and development. Yes, hardware performance is constantly improving.
Upgrades to SQL Server—especially to the optimizer, which helps determine how a
query is executed, and the query engine, which executes the query—lead to better
performance all on their own. Further, automation within SQL Server will do some
aspects of query tuning for you. At the same time, SQL Server instances are being put on
virtual machines, either locally or in hosted environments, where the hardware behavior
is not guaranteed. Databases are going to platform-as-a-service systems such as Amazon
RDS and Azure SQL Database. Object-relational mapping software such as Entity
Framework will generate most queries for you. Despite all this, you still have to deal
with fundamental database design and code generation. In short, query performance
tuning remains a vital mechanism for improving the performance of your database
management systems. The beauty of query performance tuning is that, in many cases, a
small change to an index or a SQL query can result in a far more efficient application at
a very low cost. In those cases, the increase in performance can be orders of magnitude
better than that offered by an incrementally faster CPU or a slightly better optimizer.
There are, however, many pitfalls for the unwary. As a result, a proven process is
required to ensure that you correctly identify and resolve performance bottlenecks. To
whet your appetite for the types of topics essential to honing your query optimization
skills, the following is a quick list of the query optimization aspects I cover in this book:

• Identifying problematic SQL queries

• Analyzing a query execution plan

• Evaluating the effectiveness of the current indexes

1
© Grant Fritchey 2018
G. Fritchey, SQL Server 2017 Query Performance Tuning, https://doi.org/10.1007/978-1-4842-3888-2_1
Another Random Scribd Document
with Unrelated Content
Paulina's prediction came true, and we were soon busy preparing for her
father's marriage with Miss Cottrell. It took place in our beautiful old church on
the thirty-first of July. The happy pair spent a week at Felixstowe and then
came back to "Gay Bowers" to fetch Pollie. It was with genuine regret that
Aunt Patty and I watched Mr. and Mrs. Dicks and Paulina take their departure.
How different were our feelings now from those with which we had received
the Americans and Miss Cottrell! The paying guests had become our friends.

"Au revoir!" cried Pollie as they drove away. "We are coming back some day.
And, Mr. Faulkner, please don't forget that you are going to bring Nan to
Indianapolis some time."

We watched them pass out of our sight with the sadness most partings
inevitably bring, for who could say whether we should all meet again?

Two days later, Alan's sisters came to spend their holidays at "Gay Bowers."
They were such nice, bright girls that I had no difficulty in making friends of
them, and I am thankful to say they seemed to take to me at once. The
brother, who was their guardian, was so great a hero in their eyes, that I
wonder they thought me good enough for him. It must have been, because
they thought he could not make a wrong choice.

Peggy joined us ere August was far advanced, and we became a very lively
party. By this time Jack had returned to the vicarage. I had the satisfaction of
seeing that Aunt Patty had rightly gauged the depth of his wound. If the news
of my engagement to Alan Faulkner hurt him, the blow was one from which he
quickly recovered. He and Peggy became good comrades; she wanted to
practise sketching during her stay in the country and he helped her to find
suitable "bits," and was her attendant squire on many of her expeditions.

I had heard nothing from Agneta since her return to Manchester, but the news
of my engagement brought me a kind though rather sad letter from her. She
said she thought that I and Professor Faulkner were exactly suited to each
other and she was glad I was going to be happy, for I deserved happiness and
she supposed she never had. She knew now that she had been utterly
deluded when she imagined that Ralph Marshman would make her happy.
She wanted me to know that she was convinced of his worthless character
and of what an escape she had had. She thanked me for the efforts I had
made to save her from her own folly, and she begged me to forgive her for
being so ungrateful at the time. She said she was sick of her life at home. She
wanted her parents to let her adopt a career of her own and live a more useful
life, but her mother refused to entertain the idea for a moment.
"I am trying to be patient," Agneta wrote; "You know you were always
preaching patience to me, Nan; and I mean to do some 'solid' reading every
day. Do send me a list of books you think I ought to read. I know, although you
never said so, that you thought me very ignorant when I was with you. I don't
forget either how you once said that I never should be happy as long as I
made myself the centre of my life. So I try to be unselfish and to think of other
people, but there is really very little I can do for others in the life I lead here. I
almost envy girls who have to work for themselves."

I felt very sorry for Agneta as I read her letter, and yet I should have been
glad, for, if her words were sincere, they augured for her happier days than
she had yet known. For what hope of happiness is there for any one who is
shut up in the prison-house of self? It was good for Agneta, as it had been for
me and for Paulina, to suffer, if her trouble had led her into a larger, fuller, and
more blessed life.

But the story of Aunt Patty's guests, as far as I have known them intimately,
must be brought to a close. After all, I did not stay quite twelve months at "Gay
Bowers." I went home for Christmas and I did not return. There was no longer
any thought of my going up for Matriculation. Even now I regret that I never
did so, but mother was bent upon my entering on a course of domestic
economy, and the value of that study I am daily proving.

Early in the New Year, Olive was married. It was a very pretty wedding and
everything went off charmingly; but her departure for India six weeks later left
us all with very sore hearts. Alan was duly appointed to the professorship at
Edinburgh, and now my home is in that beautiful old city, for in the following
year, at the beginning of the summer vacation, we were married.

I should like to write about that wedding, but Alan thinks I had better not begin.
My three sisters, Alan's two, and Cousin Agneta were my bridesmaids. Mr.
Upsher assisted at the ceremony, and Jack, such a handsome young soldier,
was one of the guests. He still showed himself devoted to Peggy, but I hope
he is not seriously attracted by her, for Peggy declares that she is wedded to
her art and is quite angry if any one suggests that she may marry. She is now
working hard in Paris and promises to develop into a first-rate artist in "black
and white."

Agneta made a very pretty bridesmaid and looked as happy as one could
wish. I say this on mother's authority, for really I cannot remember how any
one looked except Alan. The sun must have been in my eyes all the time, for
my recollection of everything is so vague and hazy. So it was wise of Alan to
advise me not to attempt to describe our wedding. Soon afterwards we heard
of Agneta's engagement, with her parents' approval, to a young medical man,
so I dare say she did look happy.

Alan and I always agree that "Gay Bowers" is the most delightful old country
house we have ever known. Apparently many are of the same opinion, for
aunt seldom has a room to spare in it.

THE END

Richard Clay & Sons, Limited, London and Bungay.


*** END OF THE PROJECT GUTENBERG EBOOK AUNT PATTY'S
PAYING GUESTS ***

Updated editions will replace the previous one—the old editions will
be renamed.

Creating the works from print editions not protected by U.S.


copyright law means that no one owns a United States copyright in
these works, so the Foundation (and you!) can copy and distribute it
in the United States without permission and without paying copyright
royalties. Special rules, set forth in the General Terms of Use part of
this license, apply to copying and distributing Project Gutenberg™
electronic works to protect the PROJECT GUTENBERG™ concept
and trademark. Project Gutenberg is a registered trademark, and
may not be used if you charge for an eBook, except by following the
terms of the trademark license, including paying royalties for use of
the Project Gutenberg trademark. If you do not charge anything for
copies of this eBook, complying with the trademark license is very
easy. You may use this eBook for nearly any purpose such as
creation of derivative works, reports, performances and research.
Project Gutenberg eBooks may be modified and printed and given
away—you may do practically ANYTHING in the United States with
eBooks not protected by U.S. copyright law. Redistribution is subject
to the trademark license, especially commercial redistribution.

START: FULL LICENSE


THE FULL PROJECT GUTENBERG LICENSE
PLEASE READ THIS BEFORE YOU DISTRIBUTE OR USE THIS WORK

To protect the Project Gutenberg™ mission of promoting the free


distribution of electronic works, by using or distributing this work (or
any other work associated in any way with the phrase “Project
Gutenberg”), you agree to comply with all the terms of the Full
Project Gutenberg™ License available with this file or online at
www.gutenberg.org/license.

Section 1. General Terms of Use and


Redistributing Project Gutenberg™
electronic works
1.A. By reading or using any part of this Project Gutenberg™
electronic work, you indicate that you have read, understand, agree
to and accept all the terms of this license and intellectual property
(trademark/copyright) agreement. If you do not agree to abide by all
the terms of this agreement, you must cease using and return or
destroy all copies of Project Gutenberg™ electronic works in your
possession. If you paid a fee for obtaining a copy of or access to a
Project Gutenberg™ electronic work and you do not agree to be
bound by the terms of this agreement, you may obtain a refund from
the person or entity to whom you paid the fee as set forth in
paragraph 1.E.8.

1.B. “Project Gutenberg” is a registered trademark. It may only be


used on or associated in any way with an electronic work by people
who agree to be bound by the terms of this agreement. There are a
few things that you can do with most Project Gutenberg™ electronic
works even without complying with the full terms of this agreement.
See paragraph 1.C below. There are a lot of things you can do with
Project Gutenberg™ electronic works if you follow the terms of this
agreement and help preserve free future access to Project
Gutenberg™ electronic works. See paragraph 1.E below.
1.C. The Project Gutenberg Literary Archive Foundation (“the
Foundation” or PGLAF), owns a compilation copyright in the
collection of Project Gutenberg™ electronic works. Nearly all the
individual works in the collection are in the public domain in the
United States. If an individual work is unprotected by copyright law in
the United States and you are located in the United States, we do
not claim a right to prevent you from copying, distributing,
performing, displaying or creating derivative works based on the
work as long as all references to Project Gutenberg are removed. Of
course, we hope that you will support the Project Gutenberg™
mission of promoting free access to electronic works by freely
sharing Project Gutenberg™ works in compliance with the terms of
this agreement for keeping the Project Gutenberg™ name
associated with the work. You can easily comply with the terms of
this agreement by keeping this work in the same format with its
attached full Project Gutenberg™ License when you share it without
charge with others.

1.D. The copyright laws of the place where you are located also
govern what you can do with this work. Copyright laws in most
countries are in a constant state of change. If you are outside the
United States, check the laws of your country in addition to the terms
of this agreement before downloading, copying, displaying,
performing, distributing or creating derivative works based on this
work or any other Project Gutenberg™ work. The Foundation makes
no representations concerning the copyright status of any work in
any country other than the United States.

1.E. Unless you have removed all references to Project Gutenberg:

1.E.1. The following sentence, with active links to, or other


immediate access to, the full Project Gutenberg™ License must
appear prominently whenever any copy of a Project Gutenberg™
work (any work on which the phrase “Project Gutenberg” appears, or
with which the phrase “Project Gutenberg” is associated) is
accessed, displayed, performed, viewed, copied or distributed:
This eBook is for the use of anyone anywhere in the United
States and most other parts of the world at no cost and with
almost no restrictions whatsoever. You may copy it, give it away
or re-use it under the terms of the Project Gutenberg License
included with this eBook or online at www.gutenberg.org. If you
are not located in the United States, you will have to check the
laws of the country where you are located before using this
eBook.

1.E.2. If an individual Project Gutenberg™ electronic work is derived


from texts not protected by U.S. copyright law (does not contain a
notice indicating that it is posted with permission of the copyright
holder), the work can be copied and distributed to anyone in the
United States without paying any fees or charges. If you are
redistributing or providing access to a work with the phrase “Project
Gutenberg” associated with or appearing on the work, you must
comply either with the requirements of paragraphs 1.E.1 through
1.E.7 or obtain permission for the use of the work and the Project
Gutenberg™ trademark as set forth in paragraphs 1.E.8 or 1.E.9.

1.E.3. If an individual Project Gutenberg™ electronic work is posted


with the permission of the copyright holder, your use and distribution
must comply with both paragraphs 1.E.1 through 1.E.7 and any
additional terms imposed by the copyright holder. Additional terms
will be linked to the Project Gutenberg™ License for all works posted
with the permission of the copyright holder found at the beginning of
this work.

1.E.4. Do not unlink or detach or remove the full Project


Gutenberg™ License terms from this work, or any files containing a
part of this work or any other work associated with Project
Gutenberg™.

1.E.5. Do not copy, display, perform, distribute or redistribute this


electronic work, or any part of this electronic work, without
prominently displaying the sentence set forth in paragraph 1.E.1 with
active links or immediate access to the full terms of the Project
Gutenberg™ License.
1.E.6. You may convert to and distribute this work in any binary,
compressed, marked up, nonproprietary or proprietary form,
including any word processing or hypertext form. However, if you
provide access to or distribute copies of a Project Gutenberg™ work
in a format other than “Plain Vanilla ASCII” or other format used in
the official version posted on the official Project Gutenberg™ website
(www.gutenberg.org), you must, at no additional cost, fee or expense
to the user, provide a copy, a means of exporting a copy, or a means
of obtaining a copy upon request, of the work in its original “Plain
Vanilla ASCII” or other form. Any alternate format must include the
full Project Gutenberg™ License as specified in paragraph 1.E.1.

1.E.7. Do not charge a fee for access to, viewing, displaying,


performing, copying or distributing any Project Gutenberg™ works
unless you comply with paragraph 1.E.8 or 1.E.9.

1.E.8. You may charge a reasonable fee for copies of or providing


access to or distributing Project Gutenberg™ electronic works
provided that:

• You pay a royalty fee of 20% of the gross profits you derive from
the use of Project Gutenberg™ works calculated using the
method you already use to calculate your applicable taxes. The
fee is owed to the owner of the Project Gutenberg™ trademark,
but he has agreed to donate royalties under this paragraph to
the Project Gutenberg Literary Archive Foundation. Royalty
payments must be paid within 60 days following each date on
which you prepare (or are legally required to prepare) your
periodic tax returns. Royalty payments should be clearly marked
as such and sent to the Project Gutenberg Literary Archive
Foundation at the address specified in Section 4, “Information
about donations to the Project Gutenberg Literary Archive
Foundation.”

• You provide a full refund of any money paid by a user who


notifies you in writing (or by e-mail) within 30 days of receipt that
s/he does not agree to the terms of the full Project Gutenberg™
License. You must require such a user to return or destroy all
copies of the works possessed in a physical medium and
discontinue all use of and all access to other copies of Project
Gutenberg™ works.

• You provide, in accordance with paragraph 1.F.3, a full refund of


any money paid for a work or a replacement copy, if a defect in
the electronic work is discovered and reported to you within 90
days of receipt of the work.

• You comply with all other terms of this agreement for free
distribution of Project Gutenberg™ works.

1.E.9. If you wish to charge a fee or distribute a Project Gutenberg™


electronic work or group of works on different terms than are set
forth in this agreement, you must obtain permission in writing from
the Project Gutenberg Literary Archive Foundation, the manager of
the Project Gutenberg™ trademark. Contact the Foundation as set
forth in Section 3 below.

1.F.

1.F.1. Project Gutenberg volunteers and employees expend


considerable effort to identify, do copyright research on, transcribe
and proofread works not protected by U.S. copyright law in creating
the Project Gutenberg™ collection. Despite these efforts, Project
Gutenberg™ electronic works, and the medium on which they may
be stored, may contain “Defects,” such as, but not limited to,
incomplete, inaccurate or corrupt data, transcription errors, a
copyright or other intellectual property infringement, a defective or
damaged disk or other medium, a computer virus, or computer
codes that damage or cannot be read by your equipment.

1.F.2. LIMITED WARRANTY, DISCLAIMER OF DAMAGES - Except


for the “Right of Replacement or Refund” described in paragraph
1.F.3, the Project Gutenberg Literary Archive Foundation, the owner
of the Project Gutenberg™ trademark, and any other party
distributing a Project Gutenberg™ electronic work under this
agreement, disclaim all liability to you for damages, costs and
expenses, including legal fees. YOU AGREE THAT YOU HAVE NO
REMEDIES FOR NEGLIGENCE, STRICT LIABILITY, BREACH OF
WARRANTY OR BREACH OF CONTRACT EXCEPT THOSE
PROVIDED IN PARAGRAPH 1.F.3. YOU AGREE THAT THE
FOUNDATION, THE TRADEMARK OWNER, AND ANY
DISTRIBUTOR UNDER THIS AGREEMENT WILL NOT BE LIABLE
TO YOU FOR ACTUAL, DIRECT, INDIRECT, CONSEQUENTIAL,
PUNITIVE OR INCIDENTAL DAMAGES EVEN IF YOU GIVE
NOTICE OF THE POSSIBILITY OF SUCH DAMAGE.

1.F.3. LIMITED RIGHT OF REPLACEMENT OR REFUND - If you


discover a defect in this electronic work within 90 days of receiving it,
you can receive a refund of the money (if any) you paid for it by
sending a written explanation to the person you received the work
from. If you received the work on a physical medium, you must
return the medium with your written explanation. The person or entity
that provided you with the defective work may elect to provide a
replacement copy in lieu of a refund. If you received the work
electronically, the person or entity providing it to you may choose to
give you a second opportunity to receive the work electronically in
lieu of a refund. If the second copy is also defective, you may
demand a refund in writing without further opportunities to fix the
problem.

1.F.4. Except for the limited right of replacement or refund set forth in
paragraph 1.F.3, this work is provided to you ‘AS-IS’, WITH NO
OTHER WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO WARRANTIES OF
MERCHANTABILITY OR FITNESS FOR ANY PURPOSE.

1.F.5. Some states do not allow disclaimers of certain implied


warranties or the exclusion or limitation of certain types of damages.
If any disclaimer or limitation set forth in this agreement violates the
law of the state applicable to this agreement, the agreement shall be
interpreted to make the maximum disclaimer or limitation permitted
by the applicable state law. The invalidity or unenforceability of any
provision of this agreement shall not void the remaining provisions.
1.F.6. INDEMNITY - You agree to indemnify and hold the
Foundation, the trademark owner, any agent or employee of the
Foundation, anyone providing copies of Project Gutenberg™
electronic works in accordance with this agreement, and any
volunteers associated with the production, promotion and distribution
of Project Gutenberg™ electronic works, harmless from all liability,
costs and expenses, including legal fees, that arise directly or
indirectly from any of the following which you do or cause to occur:
(a) distribution of this or any Project Gutenberg™ work, (b)
alteration, modification, or additions or deletions to any Project
Gutenberg™ work, and (c) any Defect you cause.

Section 2. Information about the Mission of


Project Gutenberg™
Project Gutenberg™ is synonymous with the free distribution of
electronic works in formats readable by the widest variety of
computers including obsolete, old, middle-aged and new computers.
It exists because of the efforts of hundreds of volunteers and
donations from people in all walks of life.

Volunteers and financial support to provide volunteers with the


assistance they need are critical to reaching Project Gutenberg™’s
goals and ensuring that the Project Gutenberg™ collection will
remain freely available for generations to come. In 2001, the Project
Gutenberg Literary Archive Foundation was created to provide a
secure and permanent future for Project Gutenberg™ and future
generations. To learn more about the Project Gutenberg Literary
Archive Foundation and how your efforts and donations can help,
see Sections 3 and 4 and the Foundation information page at
www.gutenberg.org.

Section 3. Information about the Project


Gutenberg Literary Archive Foundation
The Project Gutenberg Literary Archive Foundation is a non-profit
501(c)(3) educational corporation organized under the laws of the
state of Mississippi and granted tax exempt status by the Internal
Revenue Service. The Foundation’s EIN or federal tax identification
number is 64-6221541. Contributions to the Project Gutenberg
Literary Archive Foundation are tax deductible to the full extent
permitted by U.S. federal laws and your state’s laws.

The Foundation’s business office is located at 809 North 1500 West,


Salt Lake City, UT 84116, (801) 596-1887. Email contact links and up
to date contact information can be found at the Foundation’s website
and official page at www.gutenberg.org/contact

Section 4. Information about Donations to


the Project Gutenberg Literary Archive
Foundation
Project Gutenberg™ depends upon and cannot survive without
widespread public support and donations to carry out its mission of
increasing the number of public domain and licensed works that can
be freely distributed in machine-readable form accessible by the
widest array of equipment including outdated equipment. Many small
donations ($1 to $5,000) are particularly important to maintaining tax
exempt status with the IRS.

The Foundation is committed to complying with the laws regulating


charities and charitable donations in all 50 states of the United
States. Compliance requirements are not uniform and it takes a
considerable effort, much paperwork and many fees to meet and
keep up with these requirements. We do not solicit donations in
locations where we have not received written confirmation of
compliance. To SEND DONATIONS or determine the status of
compliance for any particular state visit www.gutenberg.org/donate.

While we cannot and do not solicit contributions from states where


we have not met the solicitation requirements, we know of no
prohibition against accepting unsolicited donations from donors in
such states who approach us with offers to donate.

International donations are gratefully accepted, but we cannot make


any statements concerning tax treatment of donations received from
outside the United States. U.S. laws alone swamp our small staff.

Please check the Project Gutenberg web pages for current donation
methods and addresses. Donations are accepted in a number of
other ways including checks, online payments and credit card
donations. To donate, please visit: www.gutenberg.org/donate.

Section 5. General Information About Project


Gutenberg™ electronic works
Professor Michael S. Hart was the originator of the Project
Gutenberg™ concept of a library of electronic works that could be
freely shared with anyone. For forty years, he produced and
distributed Project Gutenberg™ eBooks with only a loose network of
volunteer support.

Project Gutenberg™ eBooks are often created from several printed


editions, all of which are confirmed as not protected by copyright in
the U.S. unless a copyright notice is included. Thus, we do not
necessarily keep eBooks in compliance with any particular paper
edition.

Most people start at our website which has the main PG search
facility: www.gutenberg.org.

This website includes information about Project Gutenberg™,


including how to make donations to the Project Gutenberg Literary
Archive Foundation, how to help produce our new eBooks, and how
to subscribe to our email newsletter to hear about new eBooks.
Welcome to our website – the ideal destination for book lovers and
knowledge seekers. With a mission to inspire endlessly, we offer a
vast collection of books, ranging from classic literary works to
specialized publications, self-development books, and children's
literature. Each book is a new journey of discovery, expanding
knowledge and enriching the soul of the reade

Our website is not just a platform for buying books, but a bridge
connecting readers to the timeless values of culture and wisdom. With
an elegant, user-friendly interface and an intelligent search system,
we are committed to providing a quick and convenient shopping
experience. Additionally, our special promotions and home delivery
services ensure that you save time and fully enjoy the joy of reading.

Let us accompany you on the journey of exploring knowledge and


personal growth!

textbookfull.com

You might also like