2012-03-28 5 views
5

Mamy system, w którym klientom przydzielany jest produkt na zasadzie "kto pierwszy, ten lepszy".Optymalne rozwiązanie dla dużej liczby żądań w jednej tabeli bazy danych

Nasze produkty tabela zawiera wzrastających klucz główny, który rozpoczął się od zera, które używamy, aby śledzić ile produkty zostały przydzielone czyli użytkownik rezerwuje towar i zostaje przydzielona 1, następny użytkownik dostaje 2 itd

Problem polega na tym, że potencjalnie setki tysięcy użytkowników uzyska dostęp do systemu w danej godzinie. Wszyscy będą uderzać w ten jeden stół.

Ponieważ musimy upewnić się, że każdemu klientowi przydzielono tylko jeden produkt i śledzić, ile produktów zostało przydzielonych, używamy blokady rzędu dla każdego klienta uzyskującego dostęp do systemu, aby upewnić się, że pisze on do stołu przed następnym klientem. uderza w system - czyli egzekwuje regułę kto pierwszy ten lepszy.

Jesteśmy zaniepokojeni wąskim gardłem, którym jest czas przetwarzania każdego żądania wchodzącego do wersji SQL Server 2008 Enterprise Edition i blokady rzędu.

Nie możemy używać wielu serwerów, ponieważ musimy zapewnić integralność klucza pierwotnego, więc wszystko, co wymaga replikacji, nie będzie działać.

Czy ktoś zna jakieś dobre rozwiązania, które są szczególnie wydajne w obsłudze dużej liczby żądań na jednej tabeli bazy danych?

Trochę więcej informacji: Omawiana tabela zawiera zasadniczo tylko dwa pola - ID i ID klienta. Rozwiązaniem jest bezpłatne rozdanie miliona produktów - stąd oczekiwanie dużego popytu i dlaczego używanie rosnącego klucza podstawowego jako klucza ma dla nas sens - gdy klucz osiągnie milion, nie można już zarejestrować żadnych klientów. Ponadto wszystkie produkty są różne, więc przypisanie właściwego klucza jest ważne, np. pierwszych 100 klientów wprowadziło odbiór produktu o wyższej wartości niż kolejne 100 itd.

Dzięki za pomoc.

+1

Czy możesz ponownie zaatakować, dołączyć [sqlserver] i czy możesz powiedzieć mi wersję i wydanie, jeśli edytujesz pytanie i powiesz nam, że masz 'SQL2008 Enterprise Edition' na przykład, możemy być w stanie zaoferować dopasowane rozwiązania, np. Partycjonowanie tabel jest dostępne w SQL 2008 EE –

+0

Dzięki Jeremy. Dodano dodatkowe informacje. –

+0

Oczywiste pierwsze pytanie; czy usunąłeś wszystko inne z transakcji, która otrzymała klucz? Na przykład. Czy wiesz, że zanim spróbujesz zdobyć klucz, wszystko, co musisz wiedzieć, wejdź do stołu i zdobądź klucz, zanim zaczniesz robić inne rzeczy? – Karl

Odpowiedz

5

Po pierwsze, aby usunąć problem generowania kluczy, wygenerowałbym je wszystkie z góry. To tylko 1m wierszy i oznacza, że ​​nie musisz się martwić o zarządzanie procesem generowania kluczy. Oznacza to również, że nie musisz martwić się przypadkowym wygenerowaniem zbyt wielu wierszy, ponieważ po wypełnieniu tabeli wykonasz tylko UPDATE, a nie INSERT.

Jedno ważne pytanie brzmi: czy wszystkie 1-metrowe elementy są identyczne czy nie? Jeśli tak, to nie ma znaczenia, w jakiej kolejności są klucze (lub nawet jeśli mają one zamówienie), więc gdy klienci przesyłają prośby, po prostu "próbujesz" zaktualizować tabelę mniej więcej tak:

UPDATE TOP(1) dbo.Giveaway -- you can use OUTPUT to return the key value here 
SET CustomerID = @CurrentCustomerID 
WHERE CustomerID IS NULL 

IF @@ROWCOUNT = 0 -- no free items left 
PRINT 'Bad luck' 
ELSE 
PRINT 'Winner' 

Jeśli z drugiej strony przedmioty o długości 1m są inne, potrzebujesz innego rozwiązania, np. pozycja 1 to X, pozycje 2-10 to Y, 11-50 to Z itd. W takim przypadku ważne jest przypisanie klientów do kluczy w kolejności składania wniosków, więc powinieneś zajrzeć do jakiegoś systemu kolejkowania, być może za pomocą Service Broker. Każdy klient dodaje żądanie do kolejki, a procedura składowana przetwarza je pojedynczo i przypisuje im klucz wolny MAX, a następnie zwraca szczegóły dotyczące tego, co wygrał.

+0

'SET ROWCOUNT' jest przestarzałe w SQL 2008. Zamiast tego użyj' UPDATE TOP (1) '? http://msdn.microsoft.com/en-us/library/ms188774%28v=sql.100%29.aspx –

+0

@EdHarper Tak, to dobry punkt i zaktualizowałem swój przykład. Chociaż kluczową wiadomością dla OP jest oczywiście to, że nie ma znaczenia, który wiersz aktualizujesz, o ile aktualizujesz tylko jeden. – Pondlife

+0

Dzięki Pondlife. Pozycje są różne, więc wybór kolejki jest najlepszym sposobem na przyjęcie i zaakceptowanie opóźnień w przetwarzaniu każdego żądania w godzinach szczytu. Jeszcze jedno rozwiązanie, o którym myślałem, to umieszczenie wszystkich liczb nieparzystych w jednej bazie danych, a nawet w innej bazie danych, a następnie wyrównywanie obciążenia za pomocą prostego przełącznika bitowego. Wysyłaj naprzemiennych klientów do bazy danych - jakieś przemyślenia na ten temat jako rozwiązanie? Zgaduję, że prawdopodobnie przeniesie wąskie gardło do load balancera, a to prawdopodobnie będzie również wymagało kolejki? Dzięki za pomoc, bardzo docenione. –