Czy niepowiązane kolumny wpływają na czas zapytania instrukcji select?

10

Jestem po prostu ciekawy.

Powiedzmy, że masz tabelę 1 miliona rekordów / wierszy.

select order_value from store.orders

Czy ma to znaczenie, czy ta tabela ma 1 pole, 2 pola lub 100 pól w czasie rzeczywistego zapytania? Mam na myśli wszystkie pola inne niż „wartość_porządku”.

W tej chwili przekazuję dane do hurtowni danych. Czasami wrzucam do tabeli pola, które „kiedyś mogą być wykorzystane w przyszłości” - ale nie są teraz o nic pytane. Czy te „obce” pola wpłynęłyby na wybrane stwierdzenia, które ich nie zawierają, bezpośrednio lub pośrednio (no * mam na myśli)?

użytkownik45867
źródło
Istnieje mnóstwo informacji na ten temat dostępnych w Internecie. Kluczem jest uzyskiwanie najnowszych informacji wraz ze zmianami technologii. To, o co pytasz, jest tak uzależnione od konkretnej konfiguracji, że nie można udzielić bardzo dobrej odpowiedzi. Kluczową kwestią do zapamiętania jest to, że kiedy przechodzimy na dysk SSD, wiele rzeczy, które kiedyś były bardzo ważne dla wydajności, już nie ma miejsca.
Joe

Odpowiedzi:

10

To naprawdę zależy od indeksów i typów danych.

Korzystając z bazy danych przepełnienia stosu jako przykładu, tak wygląda tabela Użytkownicy:

ORZECHY

Ma PK / CX w kolumnie Id. Jest to więc całość danych tabeli posortowanych według Id.

Jako że jest to jedyny indeks, SQL musi wczytać całą pamięć (bez kolumn LOB) do pamięci, jeśli jeszcze jej nie ma.

DBCC DROPCLEANBUFFERS-- Don't run this anywhere near prod.

SET STATISTICS TIME, IO ON 

SELECT u.Id
INTO  #crap1
FROM dbo.Users AS u

Czas statystyki i profil io wygląda następująco:

Table 'Users'. Scan count 7, logical reads 80846, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

 SQL Server Execution Times:
   CPU time = 2406 ms,  elapsed time = 446 ms.

Jeśli dodam dodatkowy indeks nieklastrowany tylko na Id

CREATE INDEX ix_whatever ON dbo.Users (Id)

Mam teraz znacznie mniejszy indeks, który spełnia moje zapytanie.

DBCC DROPCLEANBUFFERS-- Don't run this anywhere near prod.

SELECT u.Id
INTO  #crap2
FROM dbo.Users AS u

Profil tutaj:

Table 'Users'. Scan count 7, logical reads 6587, physical reads 0, read-ahead reads 6549, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

 SQL Server Execution Times:
   CPU time = 2344 ms,  elapsed time = 384 ms.

Jesteśmy w stanie wykonać znacznie mniej odczytów i zaoszczędzić trochę czasu procesora.

Bez dodatkowych informacji na temat definicji tabeli nie mogę naprawdę lepiej odtworzyć tego, co próbujesz zmierzyć.

Ale mówisz, że jeśli nie ma określonego indeksu w tej samotnej kolumnie, inne kolumny / pola również zostaną przeskanowane? Czy to tylko wada związana z projektowaniem tabel magazynu rzędów? Dlaczego skanowane są niepotrzebne pola?

Tak, jest to specyficzne dla tabel magazynu wierszy. Dane są przechowywane przez wiersz na stronach danych. Nawet jeśli inne dane na stronie nie mają znaczenia dla twojego zapytania, cały wiersz> strona> indeks musi zostać wczytany do pamięci. Nie powiedziałbym, że inne kolumny są „skanowane”, tak jak skanowane są strony, na których one istnieją, w celu pobrania pojedynczej wartości odpowiadającej zapytaniu.

Na przykładzie starej książki telefonicznej: nawet jeśli czytasz tylko numery telefonów, przewracając stronę, zmieniasz nazwisko, imię, adres itp. Wraz z numerem telefonu.

Erik Darling
źródło
@ jpmc26 Może być jeszcze gorzej, ponieważ jeśli wszystkie żądane kolumny są częścią indeksu, zapytanie można obsłużyć, patrząc na indeks. Jeśli kolumny nie są indeksowane, mogą powodować załadowanie rekordu podstawowego, a nawet rekordów wtórnych dla typów tabel / kolumn bez klastra.
Christopher Schultz
12

To zależy od struktury tabeli i dostępnych indeksów.

  • Przypadek A: wspólna tabela (magazyn wierszy), bez indeksu (order_value).

    Jedynym możliwym planem wykonania jest odczytanie całej tabeli (która oczywiście różni się znacznie, gdy ma 2 do 200 kolumn, a więc kilka do kilku tysięcy bajtów szerokości).

  • Przypadek B: wspólna tabela, istnieje indeks (order_value)lub niektóre inne indeksy zawierające tę kolumnę.

    Teraz jest lepszy plan, zeskanuj cały indeks (jeden z nich) - który jest oczywiście znacznie węższy niż cała tabela, zaledwie kilka bajtów. Co sprawia, że ​​nie ma znaczenia, jeśli tabela ma 2 lub 200 kolumn. Skanowany jest tylko indeks.

  • Przypadek C: To jest tabela magazynu kolumn.

    Jak sama nazwa wskazuje, struktura tych tabel jest zorientowana na kolumny, a nie na wiersze. Indeks nie jest potrzebny, sam projekt tabeli nadaje się do odczytu całych kolumn.

ypercubeᵀᴹ
źródło
Moja wiedza na ten temat jest nieco zielona. Najbardziej konwencjonalne (powiedzmy typowa baza danych SQL Server) są tabele magazynu wierszy, prawda? Dlaczego miałaby być skanowana cała tabela, skoro trzeba zwrócić tylko jedną kolumnę / pole? Czy jest to po prostu związane z projektowaniem tabel magazynu szeregowego?
user45867,
@ user45867 tak, dane są przechowywane w wierszach (z wyjątkiem niektórych bardzo dużych kolumn, które są przechowywane na zewnątrz). Gdy SQL Server odczytuje z dysku, odczytuje całe bloki, nie może odczytać tylko części, która ma jedną kolumnę.
ypercubeᵀᴹ