Pierwsza sugestia Pradeep Adiga, ORDER BY NEWID(), jest w porządku i coś, czego używałem w przeszłości z tego powodu.

Bądź ostrożny z używaniem RAND() – w wielu kontekstach jest ono wykonywane tylko raz na oświadczenie, więc ORDER BY RAND() nie będzie miało żadnego efektu (ponieważ otrzymujesz ten sam wynik z RAND() dla każdego wiersza).

Na przykład:

SELECT display_name, RAND() FROM tr_person

zwraca każde nazwisko z naszej tabeli osób i „losową” liczbę, która jest taka sama dla każdego wiersza. Liczba ta zmienia się przy każdym uruchomieniu zapytania, ale jest taka sama dla każdego wiersza za każdym razem.

Aby pokazać, że tak samo jest w przypadku RAND() użytego w klauzuli ORDER BY, próbuję:

SELECT display_name FROM tr_person ORDER BY RAND(), display_name

Wyniki są nadal uporządkowane według nazwiska, wskazując, że wcześniejsze pole sortowania (to, które ma być losowe) nie ma wpływu, więc przypuszczalnie zawsze ma tę samą wartość.

Ordering by NEWID() działa jednak, ponieważ jeśli NEWID() nie było zawsze ponownie oceniane, cel UUIDs zostałby złamany podczas wstawiania wielu nowych wierszy w jednym statemnt z unikalnymi identyfikatorami jako ich klucz, więc:

SELECT display_name FROM tr_person ORDER BY NEWID()

porządkuje nazwy „losowo”.

Inne DBMS

Powyższe jest prawdziwe dla MSSQL (2005 i 2008 przynajmniej, i jeśli dobrze pamiętam 2000 też). Funkcja zwracająca nowy UUID powinna być obliczana za każdym razem we wszystkich DBMSach NEWID() jest pod MSSQL, ale warto to zweryfikować w dokumentacji i/lub własnymi testami. Zachowanie innych funkcji zwracających arbitralne wyniki, takich jak RAND(), jest bardziej prawdopodobne, że będzie się różnić pomiędzy DBMS, więc ponownie sprawdź dokumentację.

Widziałem również, że zamawianie wartości UUID jest ignorowane w niektórych kontekstach, ponieważ DB zakłada, że typ nie ma żadnego znaczącego uporządkowania. Jeśli okaże się, że tak jest, należy jawnie zamienić UUID na typ łańcuchowy w klauzuli porządkującej lub owinąć wokół niego inną funkcję, taką jak CHECKSUM() w SQL Server (może być niewielka różnica w wydajności, ponieważ zamawianie będzie wykonywane na wartościach 32-bitowych, a nie 128-bitowych, chociaż to, czy korzyść z tego przewyższa koszt uruchomienia CHECKSUM() na wartość, pozostawiam do przetestowania).

Side Note

Jeśli chcesz mieć arbitralne, ale nieco powtarzalne zamawianie, zamów przez jakiś względnie niekontrolowany podzbiór danych w samych wierszach. Na przykład jedno lub drugie zwróci nazwiska w arbitralnej, ale powtarzalnej kolejności:

Arbitralne, ale powtarzalne porządki nie są często przydatne w aplikacjach, choć mogą być przydatne w testowaniu, jeśli chcesz przetestować jakiś kod na wynikach w różnych zamówieniach, ale chcesz być w stanie powtórzyć każdy przebieg w ten sam sposób kilka razy (dla uzyskania średnich wyników czasowych w kilku przebiegach, lub testowania, że poprawka, którą wprowadziłeś do kodu, usuwa problem lub nieefektywność wcześniej podkreśloną przez konkretny zestaw wyników wejściowych, lub po prostu do testowania, że twój kod jest „stabilny” w tym, że zwraca ten sam wynik za każdym razem, jeśli wysłano te same dane w danej kolejności).

Tej sztuczki można również użyć do uzyskania bardziej arbitralnych wyników z funkcji, które nie pozwalają na niedeterministyczne wywołania jak NEWID() wewnątrz ich ciała. Ponownie, nie jest to coś, co prawdopodobnie będzie często przydatne w prawdziwym świecie, ale może się przydać, jeśli chcesz, aby funkcja zwróciła coś losowego, a „losowy” jest wystarczająco dobry (ale uważaj, aby pamiętać o zasadach, które określają, kiedy funkcje zdefiniowane przez użytkownika są wywoływane, tj. zwykle tylko raz na wiersz, lub twoje wyniki mogą nie być tym, czego oczekujesz/wymagasz).

Wydajność

Jak EBarr wskazuje, mogą wystąpić problemy z wydajnością z każdym z powyższych. Dla więcej niż kilku wierszy prawie na pewno zobaczysz wyjście spooled out do tempdb przed żądaną liczbą wierszy odczytywanych z powrotem w odpowiedniej kolejności, co oznacza, że nawet jeśli szukasz 10 najlepszych, możesz znaleźć pełny skan indeksu (lub gorzej, skanowanie tabeli) dzieje się wraz z ogromnym blokiem pisania do tempdb. Dlatego może być niezwykle ważne, podobnie jak w przypadku większości rzeczy, aby przeprowadzić benchmark z realistycznymi danymi przed użyciem tego w produkcji.

admin

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.

lg