Strategia di suddivisione del nodo B-tree in SQL Server per un valore monotonicamente crescente


8

Considera un indice B-tree su un valore che aumenterà sempre monotonicamente, ad esempio una colonna di tipo IDENTITÀ. Con un'implementazione B-tree convenzionale, ogni volta che un nodo è pieno, sarà diviso il 50% / 50% e finiremo con un B-tree in cui (quasi) tutti i nodi saranno pieni solo del 50%.

So che Oracle scopre quando un valore è in costante aumento e in questi casi Oracle esegue invece una divisione del 90% / 10%. In questo modo, (quasi) tutti i nodi saranno pieni al 90% e si otterrà un utilizzo della pagina molto migliore per questi casi abbastanza comuni.

Non sono stato in grado di trovare la documentazione per una funzionalità simile in SQL Server. Tuttavia, ho eseguito due esperimenti in cui ho inserito rispettivamente N numeri interi casuali e N numeri interi consecutivi in ​​un indice. Il primo caso utilizzava molte più pagine il secondo.

SQL Server offre una funzionalità simile? In tal caso: puoi indicarmi un po 'di documentazione su questa funzione?

AGGIORNAMENTO: dagli esperimenti forniti di seguito, sembra che i nodi foglia siano mantenuti non divisi e i nodi interni siano divisi 50% / 50%. Ciò rende gli alberi B sui tasti crescenti più compatti rispetto ai tasti casuali. Tuttavia, l'approccio del 90% / 10% di Oracle è ancora migliore, e cerco ancora della documentazione ufficiale che possa verificare il comportamento osservato negli esperimenti.


Sembra una risposta accettabile a questa domanda sarebbe probabilmente una documentazione che elenca tutti i vari tipi di suddivisione della pagina che possono verificarsi e quando possono verificarsi. Al momento non sono a conoscenza di tale risorsa, ma forse qualcuno qui è ...
Martin Smith,

Risposte:


4

Se sta aggiungendo una riga alla fine dell'indice, assegnerà semplicemente una nuova pagina per la riga anziché dividere la pagina finale corrente. Le prove sperimentali per questo sono di seguito (utilizza la %%physloc%%funzione che richiede SQL Server 2008). Vedi anche la discussione qui .

CREATE TABLE T
(
id int identity(1,1) PRIMARY KEY,
filler char(1000)
)
GO

INSERT INTO T
DEFAULT VALUES
GO 7

GO
SELECT sys.fn_PhysLocFormatter(%%physloc%%)
FROM T

GO

INSERT INTO T
DEFAULT VALUES

GO

SELECT sys.fn_PhysLocFormatter(%%physloc%%)
FROM T
GO

DROP TABLE T

Resi (I risultati possono variare)

(1:173:0) /*File:Page:Slot*/
(1:173:1)
(1:173:2)
(1:173:3)
(1:173:4)
(1:173:5)
(1:173:6)
(1:110:0) /*Final insert is on a new page*/

Questo sembra applicarsi solo ai nodi foglia. Questo può essere visto eseguendo il seguito e regolando il TOPvalore. Per me 622/623era il punto di interruzione tra la richiesta di una e due pagine di primo livello (potrebbe variare se hai abilitato l'isolamento dello snapshot?). Suddivide la pagina in modo equilibrato portando a spreco di spazio a questo livello.

USE tempdb;

CREATE TABLE T2
(
id int identity(1,1) PRIMARY KEY CLUSTERED,
filler char(8000)
)

INSERT INTO T2(filler)
SELECT TOP 622 'A'
FROM master..spt_values v1,  master..spt_values v2

DECLARE @index_info  TABLE
(PageFID  VARCHAR(10), 
  PagePID VARCHAR(10),   
  IAMFID   tinyint, 
  IAMPID  int, 
  ObjectID  int,
  IndexID  tinyint,
  PartitionNumber tinyint,
  PartitionID bigint,
  iam_chain_type  varchar(30),    
  PageType  tinyint, 
  IndexLevel  tinyint,
  NextPageFID  tinyint,
  NextPagePID  int,
  PrevPageFID  tinyint,
  PrevPagePID int, 
  Primary Key (PageFID, PagePID));

INSERT INTO @index_info 
    EXEC ('DBCC IND ( tempdb, T2, -1)'  ); 

DECLARE @DynSQL nvarchar(max) = 'DBCC TRACEON (3604);'
SELECT @DynSQL = @DynSQL + '
DBCC PAGE(tempdb, ' + PageFID + ', ' + PagePID + ', 3); '
FROM @index_info     
WHERE IndexLevel = 1

SET @DynSQL = @DynSQL + '
DBCC TRACEOFF(3604); '

EXEC(@DynSQL)


DROP TABLE T2

Grazie. Si noti, però, che sto chiedendo il comportamento dei nodi dell'indice B-tree, non delle pagine della tabella. Lettura interessante però. :-)
someName

1
@someName - Le pagine della tabella sono i nodi foglia dell'indice cluster implicitamente creati da PRIMARY KEY.
Martin Smith,

Ah, capisco. Questa strategia di inserimento è sicuramente efficiente in termini di spazio. Ma non riesco a vedere come questo si adatta alla struttura B-tree: con la strategia "aggiungi-a-nuova-pagina-anziché-scissione" finiamo con un lungo elenco collegato e non un albero B. Come vengono recuperati valori specifici utilizzando solo un numero logaritmico di ricerche (I / O) in questo elenco collegato?
someName

Questo è solo il livello del nodo foglia. Non appena il livello del nodo foglia avrà più di 1 pagina, ci sarà un altro livello sopra. È possibile utilizzare DBCC INDe sys.dm_db_index_physical_statsper visualizzare informazioni su questi.
Martin Smith,

Ma ogni volta che uno dei nodi non foglia sarà pieno, sarò diviso. E quella divisione, immagino, è del 50% / 50%? O 90% / 10% come fa Oracle?
someName
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.