2009-06-22 13 views
19

Mam procedura składowana, która działa z dużą ilością danych. Mam dane wstawione do tabeli tymczasowej. Całkowity przepływ zdarzeń jest cośTworzenie klucza podstawowego na stole tymczasowym - kiedy?

CREATE #TempTable (
    Col1 NUMERIC(18,0) NOT NULL, --This will not be an identity column. 
    ,Col2 INT NOT NULL, 
    ,Col3 BIGINT, 

    ,Col4 VARCHAR(25) NOT NULL, 
    --Etc... 

    -- 
    --Create primary key here? 
) 


INSERT INTO #TempTable 
SELECT ... 
FROM MyTable 
WHERE ... 

INSERT INTO #TempTable 
SELECT ... 
FROM MyTable2 
WHERE ... 

-- 
-- ...or create primary key here? 

Moje pytanie brzmi, kiedy jest najlepszy czas, aby utworzyć klucz podstawowy na moim #TempTable stole? Teoria, że ​​powinienem utworzyć ograniczenie/indeks klucza podstawowego po tym, jak wstawię wszystkie dane, ponieważ indeks musi zostać zreorganizowany podczas tworzenia informacji klucza podstawowego. Ale zdałem sobie sprawę, że moje podsumowanie może być błędne ...

W przypadku, gdy jest to istotne, typy danych, których użyłem są prawdziwe. W tabeli , Col1 i Col4 będą stanowić mój klucz podstawowy.

Aktualizacja: W moim przypadku duplikuję klucz podstawowy tabel źródłowych. Wiem, że pola, które będą stanowić mój klucz podstawowy, będą zawsze unikatowe. Nie martwię się o nieudaną tabelę zmian, jeśli dodaję klucz podstawowy na końcu.

Chociaż to na bok, moje pytanie nadal jest takie, które jest szybsze, zakładając, że oba powiodą się?

P.S. Przepraszam, jeśli to duplikat. Jest na tyle podstawowy, że może być, ale nie udało mi się znaleźć czegoś podobnego.

Odpowiedz

14

To bardzo zależy od.

Jeśli indeks klucza głównego zostanie zgrupowany po załadowaniu, cała tabela zostanie ponownie zapisana, ponieważ indeks klastrowany nie jest tak naprawdę indeksem, jest logiczną kolejnością danych. Twój plan wykonania na insertach będzie zależeć od indeksów w miejscu, gdy plan zostanie określony, a indeks klastrowany będzie na miejscu, będzie sortował przed wstawieniem. Zazwyczaj zobaczysz to w planie wykonania.

Jeśli klucz podstawowy jest zwykłym ograniczeniem, będzie to zwykły indeks (nieklastrowy), a tabela zostanie po prostu wypełniona w dowolnej kolejności określanej przez optymalizator i zaktualizowany indeks.

Myślę, że ogólnie najszybszą wydajnością (tego procesu do załadowania tabeli temp) jest zazwyczaj zapisanie danych jako sterty, a następnie zastosowanie indeksu (nieklastrowego).

Jednak, jak zauważyli inni, tworzenie indeksu może się nie udać. Ponadto tabela tymczasowa nie istnieje w izolacji. Prawdopodobnie istnieje najlepszy indeks do odczytu danych z niego do następnego kroku. Ten indeks musi być albo na miejscu, albo stworzony. Ten numer jest miejscem, w którym musisz dokonać zwrotu prędkości, aby uzyskać wiarygodność (najpierw zastosuj PK i inne ograniczenia) i przyspiesz później (przynajmniej indeks klastrowy na miejscu, jeśli masz go mieć).

+1

Interesujące. Dziękuję Ci. Pomocny. Czy mógłbyś rozwinąć niektóre przykłady? –

+0

@Cade, dla indeksu klastrowanego masz na myśli fizyczną kolejność na dysku, a nie kolejność logiczną (tabele nie mają kolejności logicznej). –

+1

Nie, porządek fizyczny na dysku może być dowolny. Indeks klastrowany to po prostu dane przechowywane w liściach w indeksie btree zamiast w stercie. Wciąż istnieje możliwość frasowania w SQL Server i na dysku. –

3

Równie dobrze możesz utworzyć klucz podstawowy przed wstawianiem - jeśli klucz podstawowy znajduje się w kolumnie tożsamości, to wstawki będą wykonywane sekwencyjnie w każdym razie i nie będzie różnicy.

+0

Nie będę używać tożsamości. Opublikowaliś my to, gdy aktualizowałem moje pytanie. Mój klucz podstawowy składa się z pola NUMERYCZNY (18,0) i VARCHAR (25). –

+0

Klucze podstawowe są domyślnie klastrowane. To uporządkuje twoje sekwencyjne porządkowanie danych w oparciu o Wartości PK. Zgadzam się z tą odpowiedzią, powinno to nastąpić przed wstawieniem. Uwaga: jeśli dodasz dodatkowe indeksy nieklastrowe. Utworzenie klastrowanego PK po spowoduje, że SQL Server przebuduje indeksy nieklastrowane. – DBAndrew

0

Nie sądzę, to sprawia, że ​​żadnej znaczącej różnicy w przypadku:

  • albo płacisz karę trochę w czasie, z każdego pojedynczego insertu
  • lub Zapłacisz większy kara po wszystkich wkładek są zrobione, ale tylko raz

Podczas tworzenia go z góry przed rozpoczęciem wkładki, ty potencjalnie mogłyby złapać naruszeń PK jak dane są wstawiane, jeśli wartość nie jest PK utworzone przez system.

Ale poza tym - żadna duża różnica, naprawdę.

Marc

+1

zakres podziałów i rejestrowania i takie tam? To nie musi być brane pod uwagę? –

1

Jeśli dodać klucz podstawowy podczas tworzenia tabeli, pierwsza wkładka będzie darmowe (bez kontrole wymagane). Druga wkładka musi tylko sprawdzić, czy jest inna od pierwszej. Trzecia wkładka musi sprawdzić dwa rzędy i tak dalej. Kontrole będą wyszukiwaniem indeksu, ponieważ istnieje unikalne ograniczenie.

Po dodaniu klucza podstawowego po wszystkich wstawkach, każdy wiersz musi zostać dopasowany do każdego innego wiersza. Zgaduję więc, że dodanie klucza początkowego na wczesnym etapie jest tańsze.

Ale może Sql Server ma naprawdę sprytny sposób sprawdzania wyjątkowości. Więc jeśli chcesz mieć pewność, zmierzyć!

+0

Nie myślałem o tym ... to jest dobre. –

0

Nie zamierzałem odpowiadać na to pytanie, ponieważ nie jestem w 100% pewny swojej wiedzy na ten temat.Ale ponieważ nie wygląda na to, że otrzymujesz wiele odpowiedzi ...

Moje zrozumienie to PK to unikalny indeks, a po wstawieniu każdego rekordu indeks jest aktualizowany i optymalizowany. Więc ... jeśli najpierw dodasz dane, a następnie utworzymy indeks, indeks zostanie zoptymalizowany tylko raz.

Tak więc, jeśli masz pewność, że twoje dane są czyste (bez duplikatów danych PK), to powiedziałbym, że wstawiam, a następnie dodaję PK.

Ale jeśli twoje dane mogą mieć zduplikowane dane PK, powiedziałabym, stwórz PK najpierw, więc zbombarduje się JAK NAJSZYBCIEJ.

+0

Dziękuję za odpowiedź. W rzeczywistości jestem pewien, że nie będę miał duplikatów ... –

1

Jeszcze ważniejsze niż względy wydajnościowe, jeśli nie jesteś ABSOLUTNA, na 100% pewności, że w tabeli zostaną wstawione niepowtarzalne wartości, najpierw utwórz klucz podstawowy. W przeciwnym razie klucz podstawowy nie zostanie utworzony.

Zapobiega to wstawianiu zduplikowanych/błędnych danych.

+0

To nie jest dla mnie problem. Rozumiem, że może to być dla niektórych, ale nie stanowi dla mnie żadnego problemu. –

+0

Myślę, że ma to sens tylko dlatego, że demonstruje to, co logicznie próbujesz robić jaśniej i pozwala silnikowi pomóc ci, gdy założenia były bezpieczne (tj. Pewność, że żadne duplikaty danych nie znajdą się w tabeli po wstawieniu) nie są już bezpieczne (np. wynikające z pewnych zmian w innej części bazy danych). – binki

6

Jeśli model odzyskiwania bazy danych jest ustawiony na prosty lub zbiorczy, SELECT ... INTO ... UNION ALL może być najszybszym rozwiązaniem. SELECT .. INTO jest operacją masową, a operacje masowe są minimalnie rejestrowane.

np

-- first, create the table 
SELECT ... 
INTO #TempTable 
FROM MyTable 
WHERE ... 
UNION ALL 
SELECT ... 
FROM MyTable2 
WHERE ... 

-- now, add a non-clustered primary key: 
-- this will *not* recreate the table in the background 
-- it will only create a separate index 
-- the table will remain stored as a heap 
ALTER TABLE #TempTable ADD PRIMARY KEY NONCLUSTERED (NonNullableKeyField) 

-- alternatively: 
-- this *will* recreate the table in the background 
-- and reorder the rows according to the primary key 
-- CLUSTERED key word is optional, primary keys are clustered by default 
ALTER TABLE #TempTable ADD PRIMARY KEY CLUSTERED (NonNullableKeyField) 

Inaczej Cade Roux miał dobrą radę Re: przed czy po.

1

Zastanawiam się, czy mogę poprawić bardzo bardzo "kosztowną" procedurę przechowywaną, pociągającą za sobą kilka sprawdzeń przy każdym wstawieniu w tabelach i natknąłem się na tę odpowiedź. W Sprocu otwiera się kilka tabel tymczasowych, które się nawzajem odwołują. Dodałem klucz podstawowy do instrukcji CREATE TABLE (mimo że moje wybory używają instrukcji WHERE NOT EXISTS do wstawienia danych i zapewnienia unikalności) i mój czas wykonania został skrócony SEVERELY. Gorąco polecam używanie kluczy podstawowych. Zawsze przynajmniej wypróbuj go, nawet jeśli uważasz, że go nie potrzebujesz.

+1

Kontekst pytania polegał w mniejszym stopniu na tym, czy utworzyć klucz podstawowy, czy nie, ale w którym momencie jest bardziej efektywny - populacja danych lub populacja danych. Wniosek poprzedzający to pytanie był taki, że klucz/indeks pomógł w czasie wykonywania. –

Powiązane problemy