2010-09-08 13 views
7

Mam do czynienia z porcjami danych, które mają 50 tys. Wierszy. ja wkładając je do bazy danych SQL przy użyciu LINQ:Szybsze wstawianie SQL?

for(int i=0;i<50000;i++) 
{ 
    DB.TableName.InsertOnSubmit 
    (
     new TableName 
     { 
      Value1 = Array[i,0], 
      Value2 = Array[i,1] 
     } 
    ); 
} 
DB.SubmitChanges(); 

To trwa około 6 minut, a ja chcę, żeby wziąć dużo mniej, jeśli to możliwe. Jakieś sugestie?

+0

Czy masz profil, aby zobaczyć, gdzie spędza większość czasu? –

+0

13.88 wkładek na sekundę wygląda bardzo kiepsko! Jaka jest twoja baza danych? –

+0

Zrobiłem bardzo prymitywne profilowanie w całym moim programie, a wstawianie zajmuje 95% czasu.Nie profilowałem wewnątrz wkładki. – sooprise

Odpowiedz

10

jeśli czytasz w pliku, lepiej byłoby użyć numeru BULK INSERT (Transact-SQL) i jeśli piszesz tyle (50K wierszy) w jednym momencie z pamięci, lepiej byłoby najpierw napisać do płaskiego pliku, a następnie użyć Zbiorcze wstawienie tego pliku.

+0

Całkowicie się zgadzam! – Stefan

+4

Aboslutely, problem polega na wstawianiu pojedynczych wkładek 50K vice one bulk insert, to zadanie, którego po prostu nie należy rozważać przy użyciu LINQ. To coś, co należy zrobić w zestawie. Wkładka BULK powinna bić to w mniej niż minutę, użyłem do wstawienia 21 milionów rekordów w 16 minut na starym wolnym serwerze. – HLGEM

+0

Jaki format ma plik danych? Czy mogę po prostu przeciąć wartości? – sooprise

1

Ponieważ robisz prostą wkładkę i nie zyskujesz zbyt wiele na korzystaniu z LinqToSql, spójrz na SqlBulkCopy, usunie ona większość podróży w obie strony i zmniejszy obciążenie również po stronie serwera Sql. Będziesz musiał wprowadzić niewiele zmian w kodowaniu, aby go użyć.

Zobacz także wstępne sortowanie danych według kolumny, na której jest indeksowana tabela, ponieważ spowoduje to lepsze trafienia w pamięci podręcznej, gdy SQL-Server zaktualizuje tabelę.

Należy również rozważyć, czy należy przesłać dane do tymczasowej tabeli tymczasowej, która nie jest indeksowana, a następnie do zapisanego procesu, który zostanie wstawiony do głównej tabeli za pomocą pojedynczego polecenia SQL. Ten może pozwolić SqlServer rozprzestrzenić pracę indeksowania na wszystkich procesorach.

1

Jest wiele rzeczy, które musisz sprawdzić/zrobić.

  1. Ile miejsca na dysku zostało przydzielone do bazy danych? Czy jest wystarczająco dużo wolnego, aby wykonać wszystkie wkładki bez automatycznego zwiększania rozmiaru? Jeśli nie, zwiększ rozmiar pliku bazy danych, ponieważ musi zatrzymywać się co tylu insertów, aby automatycznie zmienić rozmiar samego db.

  2. NIE wkładaj pojedynczych wkładek. Trwają zbyt długo. Zamiast tego należy użyć parametrów wartości tabeli (sql 2008), kopii zbiorczej sql lub pojedynczej instrukcji wstawiania (w tej kolejności preferencji).

  3. upuść wszystkie indeksy na tej tabeli i odtwórz je po załadowaniu. Przy tak wielu wstawkach i tak prawdopodobnie zostaną rozerwani do piekła.

  4. Jeśli masz jakieś wyzwalacze, rozważ upuszczenie ich do momentu zakończenia ładowania.

  5. Czy masz wystarczającą ilość pamięci RAM na serwerze bazy danych? Musisz sprawdzić sam serwer, aby sprawdzić, czy zużywa WSZYSTKIE dostępne RAM? Jeśli tak, możesz rozważyć zrobienie restartu przed załadowaniem ... Serwer sql ma tendencję do po prostu konsumowania i trzymania się wszystkiego, co może dostać w swoje ręce.

  6. Wzdłuż linii pamięci RAM, chcemy utrzymywać wystarczającą ilość pamięci RAM na serwerze, aby pomieścić całą bazę danych w pamięci. Nie jestem pewien, czy jest to wykonalne dla ciebie, czy nie.

  7. Jaka jest szybkość dysku? Czy głębokość kolejki jest dość długa? Poza wymianą sprzętu nie ma tu wiele do zrobienia.

Powiązane problemy