페이지 읽기Reading Pages

이 항목 적용 대상: 예SQL Server없습니다Azure SQL 데이터베이스없습니다Azure SQL 데이터 웨어하우스 없습니다 병렬 데이터 웨어하우스THIS TOPIC APPLIES TO: yesSQL ServernoAzure SQL DatabasenoAzure SQL Data Warehouse noParallel Data Warehouse

SQL Server 데이터베이스 엔진Database Engine 인스턴스의 I/O에는 논리적 읽기 수 및 물리적 읽기 수가 포함되어 있습니다.The I/O from an instance of the SQL Server 데이터베이스 엔진Database Engine includes logical and physical reads. 논리적 읽기는 데이터베이스 엔진Database Engine버퍼 캐시에서 페이지를 요청할 때마다 발생합니다.A logical read occurs every time the 데이터베이스 엔진Database Engine requests a page from the buffer cache. 페이지가 현재 버퍼 캐시에 없는 경우 물리적 읽기가 먼저 디스크의 페이지를 캐시로 복사합니다.If the page is not currently in the buffer cache, a physical read first copies the page from disk into the cache.

데이터베이스 엔진Database Engine 인스턴스로 생성된 읽기 요청은 관계형 엔진에 의해 제어되고 저장소 엔진에 의해 최적화됩니다.The read requests generated by an instance of the 데이터베이스 엔진Database Engine are controlled by the relational engine and optimized by the storage engine. 관계형 엔진은 테이블 검색, 인덱스 검색 또는 키 사용 읽기와 같은 가장 효과적인 액세스 방법을 결정합니다. 저장소 엔진의 액세스 방법 및 버퍼 관리자 구성 요소는 수행할 일반적인 읽기 패턴을 결정하고 액세스 방법을 구현하는 데 필요한 읽기를 최적화합니다.The relational engine determines the most effective access method (such as a table scan, an index scan, or a keyed read); the access methods and buffer manager components of the storage engine determine the general pattern of reads to perform, and optimize the reads required to implement the access method. 일괄 처리를 실행하는 스레드는 읽기 일정을 계획합니다.The thread executing the batch schedules the reads.

미리 읽기Read-Ahead

데이터베이스 엔진Database Engine 은 미리 읽기라고 하는 성능 최적화 메커니즘을 지원합니다.The 데이터베이스 엔진Database Engine supports a performance optimization mechanism called read-ahead. 미리 읽기는 쿼리 실행 계획을 수행하는 데 필요한 데이터 및 인덱스 페이지를 예상하고 페이지가 쿼리에서 실제로 사용되기 전에 해당 페이지를 버퍼 캐시로 가져옵니다.Read-ahead anticipates the data and index pages needed to fulfill a query execution plan and brings the pages into the buffer cache before they are actually used by the query. 이렇게 하면 계산과 I/O가 동시에 수행되어 CPU와 디스크를 모두 충분히 활용할 수 있습니다.This allows computation and I/O to overlap, taking full advantage of both the CPU and the disk.

미리 읽기 메커니즘을 통해 데이터베이스 엔진Database Engine 에서는 한 파일에서 연속하는 최대 64페이지(512KB)를 읽을 수 있습니다.The read-ahead mechanism allows the 데이터베이스 엔진Database Engine to read up to 64 contiguous pages (512KB) from one file. 읽기는 버퍼 캐시에서 연속되지 않은 적절한 수의 버퍼에 대해 단일 분산 수집 읽기로 수행됩니다.The read is performed as a single scatter-gather read to the appropriate number of (probably non-contiguous) buffers in the buffer cache. 해당 범위의 페이지 중 버퍼 캐시에 이미 존재하는 페이지가 있을 경우 읽기가 완료된 후 읽기에서 해당 페이지가 삭제됩니다.If any of the pages in the range are already present in the buffer cache, the corresponding page from the read will be discarded when the read completes. 해당 페이지가 캐시에 이미 있을 경우 완료 후 페이지 범위가 "잘릴" 수도 있습니다.The range of pages may also be "trimmed" from either end if the corresponding pages are already present in the cache.

미리 읽기에는 데이터 페이지 읽기와 인덱스 페이지 읽기가 있습니다.There are two kinds of read-ahead: one for data pages and one for index pages.

데이터 페이지 읽기Reading Data Pages

데이터베이스 엔진Database Engine에서는 데이터 페이지를 읽을 때 테이블 검색을 사용하면 매우 효율적입니다.Table scans used to read data pages are very efficient in the 데이터베이스 엔진Database Engine. SQL Server Database에 있는 IAM(Index Allocation Map) 페이지에 테이블 또는 인덱스에서 사용하는 익스텐트가 나열됩니다.The index allocation map (IAM) pages in a SQL Server database list the extents used by a table or index. 저장소 엔진은 IAM을 읽어서 읽어야 하는 정렬된 디스크 주소 목록을 작성할 수 있습니다.The storage engine can read the IAM to build a sorted list of the disk addresses that must be read. 이렇게 하면 저장소 엔진이 디스크에서의 I/O 위치를 기반으로 하여 순서대로 수행되는 대형 순차 읽기로 해당 I/O를 최적화할 수 있습니다.This allows the storage engine to optimize its I/Os as large sequential reads that are performed in sequence, based on their location on the disk. IAM 페이지에 대한 자세한 내용은 개체에서 사용하는 공간 관리를 참조하세요.For more information about IAM pages, see Managing Space Used by Objects.

인덱스 페이지 읽기Reading Index Pages

저장소 엔진은 인덱스 페이지를 키 순서로 읽습니다.The storage engine reads index pages serially in key order. 예를 들어 다음 그림은 키 집합을 포함하는 리프 페이지 집합을 간단히 보여 주고 리프 페이지를 매핑하는 중간 인덱스 노드를 보여 줍니다.For example, this illustration shows a simplified representation of a set of leaf pages that contains a set of keys and the intermediate index node mapping the leaf pages. 인덱스 페이지의 구조에 대한 자세한 내용은 클러스터형 인덱스 구조를 참조하세요.For more information about the structure of pages in an index, see Clustered Index Structures.

Reading_Pages

저장소 엔진은 리프 수준 위의 중간 인덱스 페이지에 있는 정보를 사용하여 키를 포함하는 페이지의 직렬 미리 읽기를 예약합니다.The storage engine uses the information in the intermediate index page above the leaf level to schedule serial read-aheads for the pages that contain the keys. ABC에서 DEF까지의 모든 키에 대해 요청이 수행된 경우 저장소 엔진은 리프 페이지 위의 인덱스 페이지를 먼저 읽습니다.If a request is made for all the keys from ABC to DEF, the storage engine first reads the index page above the leaf page. 그러나 504페이지에서 556페이지까지(지정된 범위의 키를 포함하는 마지막 페이지) 순서대로 각 데이터 페이지를 단순히 읽지는 않습니다.However, it does not just read each data page in sequence from page 504 to page 556 (the last page with keys in the specified range). 대신 저장소 엔진은 중간 인덱스 페이지를 검색하고 읽어야 하는 리프 페이지 목록을 작성합니다.Instead, the storage engine scans the intermediate index page and builds a list of the leaf pages that must be read. 그런 다음 저장소 엔진은 키 순서대로 모든 읽기를 예약합니다.The storage engine then schedules all the reads in key order. 또한 저장소 엔진은 페이지 504/505 및 527/528이 인접해 있다고 인식하고 단일 분산 읽기를 수행하여 단일 작업으로 인접한 페이지들을 검색합니다.The storage engine also recognizes that pages 504/505 and 527/528 are contiguous and performs a single scatter read to retrieve the adjacent pages in a single operation. 직렬 작업에서 검색할 페이지가 많으면 저장소 엔진은 한 번에 읽을 블록을 예약합니다.When there are many pages to be retrieved in a serial operation, the storage engine schedules a block of reads at a time. 이러한 읽기 하위 집합이 완료되면 저장소 엔진은 읽어야 할 모든 내용이 예약될 때까지 같은 수의 새 읽기를 예약합니다.When a subset of these reads is completed, the storage engine schedules an equal number of new reads until all the required reads have been scheduled.

저장소 엔진은 사전 인출을 사용하여 비클러스터형 인덱스의 기본 테이블 조회 속도를 향상시킵니다.The storage engine uses prefetching to speed base table lookups from nonclustered indexes. 비클러스터형 인덱스의 리프 행은 각각의 특정 키 값을 포함하는 데이터 행에 대한 포인터를 포함합니다.The leaf rows of a nonclustered index contain pointers to the data rows that contain each specific key value. 저장소 엔진이 비클러스터형 인덱스의 리프 페이지를 읽을 때 포인터가 이미 검색된 데이터 행에 대한 비동기 읽기도 예약하기 시작합니다.As the storage engine reads through the leaf pages of the nonclustered index, it also starts scheduling asynchronous reads for the data rows whose pointers have already been retrieved. 이를 통해 저장소 엔진은 비클러스터형 인덱스의 검색이 완료되기 전에 기본 테이블의 데이터 행을 검색할 수 있습니다.This allows the storage engine to retrieve data rows from the underlying table before it has completed the scan of the nonclustered index. 사전 인출은 테이블에 클러스터형 인덱스가 포함되었는지 여부에 관계없이 사용됩니다.Prefetching is used regardless of whether the table has a clustered index. SQL Server Enterprise에서는 다른 버전의 SQL Server보다 많은 사전 인출을 사용하므로 더 많은 페이지를 미리 읽을 수 있습니다.SQL Server Enterprise uses more prefetching than other editions of SQL Server, allowing more pages to be read ahead. 사전 인출 수준은 어느 버전에서도 구성할 수 없습니다.The level of prefetching is not configurable in any edition. 비클러스터형 인덱스에 대한 자세한 내용은 비클러스터형 인덱스 구조를 참조하세요.For more information about nonclustered indexes, see Nonclustered Index Structures.

고급 검색Advanced Scanning

SQL Server Enterprise의 고급 검색 기능을 사용하여 여러 태스크에서 전체 테이블 검색을 공유할 수 있습니다.In SQL Server Enterprise, the advanced scan feature allows multiple tasks to share full table scans. Transact-SQL 문의 실행 계획이 테이블의 데이터 페이지 검색을 요구하고 데이터베이스 엔진Database Engine 에서 테이블이 이미 다른 실행 계획에 대해 검색되고 있음을 감지하는 경우 데이터베이스 엔진Database Engine 은 두 번째 검색의 현재 위치에서 두 번째 검색을 첫 번째 실행 계획에 조인합니다.If the execution plan of a Transact-SQL statement requires a scan of the data pages in a table and the 데이터베이스 엔진Database Engine detects that the table is already being scanned for another execution plan, the 데이터베이스 엔진Database Engine joins the second scan to the first, at the current location of the second scan. 데이터베이스 엔진Database Engine 은 각 페이지를 한 번 읽고 각 페이지의 행을 두 실행 계획에 전달합니다.The 데이터베이스 엔진Database Engine reads each page one time and passes the rows from each page to both execution plans. 이 작업은 테이블 끝에 도달할 때까지 계속됩니다.This continues until the end of the table is reached.

테이블 끝에서 첫 번째 실행 계획에 완전한 검색 결과가 포함되지만 두 번째 실행 계획은 진행 중인 검색을 조인하기 전에 읽어오는 데이터 페이지를 계속 검색해야 합니다.At that point, the first execution plan has the complete results of a scan, but the second execution plan must still retrieve the data pages that were read before it joined the in-progress scan. 그런 다음 두 번째 실행 계획 검색은 테이블의 첫 번째 데이터 페이지로 다시 넘어가고 첫 번째 검색을 조인한 지점까지 검색이 진행됩니다.The scan for the second execution plan then wraps back to the first data page of the table and scans forward to where it joined the first scan. 이런 방식으로 원하는 수만큼 검색을 결합할 수 있습니다.Any number of scans can be combined like this. 데이터베이스 엔진Database Engine 은 모든 검색을 완료할 때까지 데이터 페이지를 계속 루핑합니다.The 데이터베이스 엔진Database Engine will keep looping through the data pages until it has completed all the scans. 이 메커니즘은 ORDER BY 절 없이 SELECT 문에서 반환된 결과의 순서를 보장할 수 없기 때문에 "회전목마(merry-go-round) 검색"이라고도 합니다.This mechanism is also called "merry-go-round scanning" and demonstrates why the order of the results returned from a SELECT statement cannot be guaranteed without an ORDER BY clause.

예를 들어 500,000개의 페이지를 포함하는 테이블이 있다고 합시다.For example, assume that you have a table with 500,000 pages. UserA는 테이블의 검색을 요청하는 Transact-SQL 문을 실행합니다.UserA executes a Transact-SQL statement that requires a scan of the table. 해당 검색이 100,000개의 페이지를 처리할 때 UserB가 동일한 테이블을 검색하는 다른 Transact-SQL 문을 실행합니다.When that scan has processed 100,000 pages, UserB executes another Transact-SQL statement that scans the same table. 데이터베이스 엔진Database Engine 은 100,001페이지 이후의 페이지에 대해 하나의 읽기 요청 집합을 예약하고 각 페이지의 행을 두 검색에 다시 전달합니다.The 데이터베이스 엔진Database Engine schedules one set of read requests for pages after 100,001, and passes the rows from each page back to both scans. 200,000번째 페이지를 검색할 때 UserC가 동일한 테이블을 검색하는 다른 Transact-SQL 문을 실행합니다.When the scan reaches the 200,000th page, UserC executes another Transact-SQL statement that scans the same table. 200,001페이지부터 데이터베이스 엔진Database Engine 은 읽고 있는 각 페이지의 행을 세 가지 검색에 모두 다시 전달합니다.Starting with page 200,001, the 데이터베이스 엔진Database Engine passes the rows from each page it reads back to all three scans. 500,000번째 행을 읽고 나면 UserA에 대한 검색이 완료되고 UserB 및 UserC에 대한 검색이 다시 시작되며 1페이지부터 다시 읽기 시작합니다.After it reads the 500,000th row, the scan for UserA is complete, and the scans for UserB and UserC wrap back and start to read the pages starting with page 1. 데이터베이스 엔진Database Engine 이 100,000페이지에 도달하면 UserB의 검색이 완료됩니다.When the 데이터베이스 엔진Database Engine gets to page 100,000, the scan for UserB is completed. 그런 다음 200,000페이지를 읽을 때까지 UserC에 대한 검색이 계속됩니다.The scan for UserC then keeps going alone until it reads page 200,000. 이 페이지가 되면 모든 검색이 완료됩니다.At this point, all the scans have been completed.

고급 검색을 사용하지 않는 경우 각 사용자는 버퍼 공간을 최대한 사용하려고 하며 이로 인해 디스크 충돌 경합이 발생합니다.Without advanced scanning, each user would have to compete for buffer space and cause disk arm contention. 그러면 같은 페이지를 여러 사용자가 한 번에 읽고 공유하는 대신 각 사용자가 한 번씩 읽게 되므로 성능이 저하되고 리소스 처리 시간이 소모됩니다.The same pages would then be read once for each user, instead of read one time and shared by multiple users, slowing down performance and taxing resources.

관련 항목:See Also

페이지 및 익스텐트 아키텍처 가이드 Pages and Extents Architecture Guide
페이지 쓰기Writing Pages