Влияет ли не релевантные столбцы на время запроса операторов выбора?

10

Мне просто интересно.

Допустим, у вас есть таблица из 1 миллиона записей / строк.

select order_value from store.orders

Имеет ли значение, имеет ли эта таблица 1 поле, 2 поля или 100 полей в реальном времени запроса? Я имею в виду все поля, кроме "order_value".

Прямо сейчас я отправляю данные в хранилище данных. Иногда я добавляю в таблицу поля, которые «могут быть использованы в будущем, когда-нибудь» - но они сейчас ни к чему не обращаются. Могут ли эти «посторонние» поля повлиять на операторы выбора, которые не включают их, прямо или косвенно (нет, я имею в виду)?

user45867
источник
В интернете есть масса информации по этому вопросу. Ключ - получение самой последней информации по мере изменения технологий. То, что вы спрашиваете, настолько зависит от вашей конкретной установки, что невозможно дать очень хороший ответ. Ключевой момент, который следует помнить, заключается в том, что при переходе на SSD многие вещи, которые когда-то были очень важны для производительности, перестали иметь место.
Джо

Ответы:

10

Это действительно зависит от индексов и типов данных.

Используя базу данных Stack Overflow в качестве примера, вот как выглядит таблица Users:

NUTS

У него есть PK / CX в столбце Id. Таким образом, это полные данные таблицы, отсортированные по идентификатору.

Учитывая это как единственный индекс, SQL должен прочитать все это (без столбцов больших объектов) в память, если его там еще нет.

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

SET STATISTICS TIME, IO ON 

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

Статистика по времени и профилю io выглядит следующим образом:

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.

Если я добавлю дополнительный некластеризованный индекс только Id

CREATE INDEX ix_whatever ON dbo.Users (Id)

Теперь у меня есть намного меньший индекс, который удовлетворяет моему запросу.

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

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

Профиль здесь:

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.

Мы можем выполнять намного меньше операций чтения и сэкономить немного процессорного времени.

Без дополнительной информации о вашем определении таблицы я не смогу воспроизвести то, что вы пытаетесь измерить лучше.

Но вы говорите, что если в этом одиночном столбце нет определенного индекса, другие столбцы / поля также будут сканироваться? Это просто недостаток, свойственный дизайну таблиц rowstore? Почему неактуальные поля будут сканироваться?

Да, это относится к таблицам хранилища строк. Данные хранятся в строке на страницах данных. Даже если другие данные на странице не имеют отношения к вашему запросу, вся эта строка> page> index должна быть считана в память. Я бы не сказал, что другие столбцы «сканируются» настолько, насколько сканируются страницы, на которых они существуют, чтобы получить единственное значение, относящееся к запросу.

Используя старый пример телефонной книги: даже если вы просто читаете телефонные номера, когда вы переворачиваете страницу, вы поворачиваете фамилию, имя, адрес и т. Д. Вместе с номером телефона.

Эрик Дарлинг
источник
@ jpmc26 Это может быть еще хуже, потому что, если все запрошенные столбцы являются частью индекса, запрос может быть обработан просто путем просмотра индекса. Если столбцы не проиндексированы, они могут привести к загрузке первичной записи и даже вторичных записей для некастрированных типов таблиц / столбцов.
Кристофер Шульц
12

Это зависит от структуры таблицы и доступных индексов.

  • Случай A: общая таблица (rowstore), без индекса (order_value).

    Единственный возможный план выполнения - прочитать всю таблицу (которая, конечно, сильно отличается, когда она имеет размер 2 к 200 столбцам, поэтому ширина составляет несколько к нескольким тысячам байтов).

  • Случай B: общая таблица, есть индекс (order_value)или некоторые другие индексы, которые включают этот столбец.

    Теперь есть лучший план, отсканируйте весь индекс (один из них) - который, конечно, гораздо более узкий, чем вся таблица, всего несколько байтов. Что делает неактуальным, если таблица имеет 2 или 200 столбцов. Только индекс сканируется.

  • Случай C: это таблица columnstore.

    Как следует из названия, структура этих таблиц ориентирована по столбцам, а не по строкам. Индекс не нужен, сам дизайн таблицы подходит для чтения целых столбцов.

ypercubeᵀᴹ
источник
Мои знания в этом вопросе немного зеленые. Это наиболее обычная (скажем, типичная база данных SQL Server) таблица хранилищ строк, верно? Зачем сканировать всю таблицу, если нужно вернуть только один столбец / поле? Это просто присуще дизайну таблиц rowstore?
user45867
@ user45867 да, данные хранятся в строках (за исключением некоторых очень больших столбцов, которые хранятся снаружи). Когда SQL Server читает с диска, он читает целыми блоками, он не может читать только часть, которая имеет один столбец.
ypercubeᵀᴹ