Оригинална поръчка за вмъкване с клъстерен индекс

Имам въпрос относно клъстерния индекс.

В клъстерираните индекси самите възли на листово ниво държат данните в сортиран ред, нали?

Тоест, с всяко вмъкване/актуализиране/изтриване, възлите се разместват отново, за да се поддържа сортираният ред.

И така, как данните могат да бъдат извлечени от него в реда, в който са били въведени?

Представете си, че следните данни са вмъкнати в дадения ред: 1,7,4,5,2 и в това поле е създаден клъстерен индекс.

Така че данните ще се съхраняват вътрешно в реда 1,2,4,5,7, нали?

Така че това може да улесни по-бързото търсене на конкретна стойност, но какво ще стане, ако потребителят иска първите 3 стойности в реда, който е въвел?

Те могат ли да бъдат извлечени по някакъв начин или трябва да присвоя нарастващ идентификатор за всеки вмъкнат ред, да декларирам неклъстерен индекс върху него и да предоставя данните за първите 3 записа въз основа на сортирането на записите в това id-поле?


person SexyBeast    schedule 01.07.2012    source източник
comment
Да, ще трябва да добавите допълнителна колона, представляваща или инкрементален сурогат, напр. identity INT или алтернативно някаква форма на механизъм за автоматично маркиране на времето за повторно проследяване на оригиналната поръчка за вмъкване.   -  person StuartLC    schedule 01.07.2012
comment
И така, как да изберем дали да създадем групиран индекс върху стойността на полето или групиран индекс върху стойността на id? Така е, че когато заявките, които идват по-често, са от този тип Изберете 6-те реда, започвайки от 3-тия ред, трябва да избера id като групиран ключ и когато заявките като Изберете запис, където стойност = 45 идва по-често, трябва да задам групиран индекс на стойността на полето?   -  person SexyBeast    schedule 01.07.2012
comment
Но току-що научих, че не мога нито да създам повече от 1 клъстериран индекс в една таблица, нито мога да създам както клъстерен, така и неклъстерен индекс в една и съща таблица. И така, как мога да създам 2 индекса (единият от които поне трябва да бъде групиран, за да улесни бързото търсене) на 2 различни полета тук?   -  person SexyBeast    schedule 01.07.2012
comment
Можете да създадете множество неклъстерирани индекси на таблица в допълнение към нула или един клъстерен индекс.   -  person Martin Smith    schedule 02.07.2012


Отговори (3)


(Отговори, базирани на SQL Server - въпросът не уточнява 100%)

В клъстерираните индекси самите възли на листово ниво държат данните в сортиран ред, нали?

Това не е съвсем правилно, данните могат да се съхраняват във всякакъв ред на листа, но масивът от слотове на страницата всъщност е редът, в който данните се четат извън страницата - не физическият ред на данните.

Тоест, с всяко вмъкване/актуализиране/изтриване, възлите се разместват отново, за да се поддържа сортираният ред.

Възли (напр. страниците се разделят и указателите напред/назад в списъка с двойни връзки се променят), но вътре в страницата масивите от слотове все още са обектът, който запазва реда, самите редове няма да бъдат разбъркани, за да съответстват на реда на масива от слотове.

И така, как данните могат да бъдат извлечени от него в реда, в който са били въведени?

Обикновено не е гарантирано, че ще бъде в точния ред - това обикновено се случва на стегната страница, където масивът от слотове е по-представителен за реда, но отново не е гарантирано.

Представете си, че следните данни са вмъкнати в дадения ред: 1,7,4,5,2 и в това поле е създаден групиран индекс. Така че данните ще се съхраняват вътрешно в ред 1,2,4,5,7, нали?

Не, ще се съхранява 1,7,4,5,2 на страницата, но масивът от слотове ще прочете адресите на страницата като 7,5,4,2,1 (конструира се от края на страницата назад , така че четете наобратно.)

Така че това може да улесни по-бързото търсене на конкретна стойност, но какво ще стане, ако потребителят иска първите 3 стойности в реда, който е въвел?

Някак несъществено в този случай - освен че няма такава гаранция за подреждане, SQL ще прочете цялата страница в паметта. Ако искате да научите повече за SQL Internals на такова ниво, все пак бих препоръчал книгата Kalen Delaneys SQL Internals като един от най-добрите източници.

Ако искате някаква информация относно реда за вмъкване, предлагам някакъв вид inserted_timestamp

person Andrew    schedule 01.07.2012
comment
Това не е съвсем правилно, данните могат да се съхраняват във всякакъв ред на листа, но масивът от слотове на страницата всъщност е редът, в който данните се четат извън страницата - не физическият ред на данните. - Но намерих на mssqltips.com/ sqlservertip/1254/clustered-tables-vs-heap-tables под параграфа Клъстерирана таблица, че Данните се съхраняват в ред въз основа на ключа на клъстерирания индекс. Моля, обяснете кое е правилното или всъщност това твърдение е едно и също. - person SexyBeast; 01.07.2012
comment
Те са обяснения с различна дълбочина на технически детайли. Можете да го разглеждате като високо ниво като съхранено в ред - което не обръща внимание на това как SQL Server физически прави това - на по-подробно ниво ще научите за страници, слот масиви и как клъстерен индекс поддържа реда и т.н. - person Andrew; 01.07.2012
comment
Моля, обяснете какво се има предвид под съхраняване на данни в слотовете на масива в един ред, докато се четат в друг ред. Всички книги, които преглеждам, посочват, че в клъстерирания индекс листовите възли са местата, където се съхраняват данните (за разлика от неклъстерирания, където те са просто указатели към действителните страници с данни) и се съхраняват в сортиран ред и сървърът поддържа сортирания ред с всяко актуализиране/вмъкване/изтриване. - person SexyBeast; 01.07.2012
comment
Те се съхраняват в двойно свързан списък от страници, обхождайте този списък по ред и имате своя клъстериран индекс. Това не казва нищо за това как страниците се съхраняват на диска или дали данните на отделна страница са в ред, масивът от слотове е редът в рамките на отделна страница. Пълните обяснения изискват много повече място/време от коментарите по даден въпрос - person Andrew; 02.07.2012
comment
Добре тогава, моля, дайте връзка/книга, където мога да ги намеря в дълбочина. Искам да кажа, че никоя от книгите или уебсайтовете не казва нищо за двойно свързани списъци и слот-матрици, всичко, което казват е, че листовите възли съдържат данните и те са в сортиран ред. - person SexyBeast; 02.07.2012
comment
Споменато в моя отговор - Kalen Delaney, SQL Server Internals - считано от мнозина за вътрешната библия. Някои блогове покриват и това ниво на детайлност, прочетете блоговете на sqlskills, например този на Пол Рандал: sqlskills.com /blogs/paul - person Andrew; 02.07.2012
comment
Но изчакайте малко, ако в клъстериран индекс листовите страници не съдържат данните, а по-скоро указатели (чрез двойно свързани списъци, както казвате), каква е разликата между този и не-клъстерен индекс? И в последния листните страници съдържат указатели към действителните данни. - person SexyBeast; 02.07.2012
comment
Не съм казал, че листните страници не съдържат данни. Листната страница има заглавка (където живеят различни неща, като указатели) и част с данни. - person Andrew; 02.07.2012
comment

Звучи ми сякаш искаш клеймо за време на редовете си. Обикновено поставям следните колони във всички таблици, които създавам (за проверка):

timecreated
timemodified
createdby
modifiedby
deleted

Тези колони ви уведомяват кой е създал реда и кога, кога е бил последно модифициран и от кого и по избор „меко изтриване“ на реда, като зададете изтрито на true. Разбира се, всички други ваши заявки в системата ще трябва да проверят изтритата булева стойност, за да работи мекото изтриване.

person Hogan    schedule 01.07.2012

Данните в таблицата се сортират според реда на клъстерирания индекс. Можете да имате само ЕДИН клъстерен индекс на всяка таблица, ако искате да проверите първите 3 стойности в реда, който той е вмъкнал,

ИЗПОЛЗВАЙТЕ AdventureWorks

go

CREATE TABLE myTable99(
Col1 int IDENTITY(1,1) PRIMARY KEY , Col2 Char(1) , Col3 datetime DEFAULT getdate()

) GO

INSERT INTO myTable99(Col2) SELECT 'A' UNION ALL SELECT 'B' UNION ALL SELECT 'C' GO

ИЗБЕРЕТЕ * ОТ myTable99 ПОРЪЧАЙТЕ ОТ 3 GO

ПУСКАНЕ НА МАСА myTable99 GO

Друг метод може да бъде:

CREATE TABLE CounterData]( [CounterDataID] [bigint] IDENTITY(1,1) NOT NULL, [DateTimeID] [bigint] NOT NULL, [Value] [float] NULL ) НА [PRIMARY]

СЪЗДАВАЙТЕ УНИКАЛЕН КЛУСТЕРИРАН ИНДЕКС [IX_DateTime_CounterDataID] НА [PK].[CounterData]

(

[DateTimeID] ASC,
[CounterDataID] ASC

)

СЪС

(PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) НА [PRIMARY] GO

person Community    schedule 01.07.2012
comment
Така че основно това, което казвате, е да съхраните допълнителна част от данните (в този случай клеймо за време) като сурогат и да извлечете запис последователно въз основа на това, като същевременно произволно въз основа на клъстерирания индекс от самия сървър, нали? - person SexyBeast; 01.07.2012