Я хочу улучшить производительность запроса, который выбирает несколько столбцов из таблицы. было интересно, повлияет ли ограничение количества столбцов на производительность запроса.
влияние количества проекций на производительность запроса
Ответы (6)
Я думаю, что уменьшение количества столбцов окажет лишь очень ограниченное влияние на скорость запроса, но может оказать большее влияние на скорость передачи данных. Чем меньше данных вы выберете, тем меньше данных потребуется передать по сети в ваше приложение.
Я могу неправильно понять вопрос, но все же:
Абсолютное количество выбранных вами столбцов не имеет большого значения. Однако выбор столбцов, которые могут существенно различаться в зависимости от того, как индексируется таблица.
Если вы выбираете только столбцы, которые охватываются индексом, то механизм БД может использовать только индекс для запроса, даже не извлекая данные таблицы. Однако, если вы используете хотя бы один непокрытый столбец, он должен получить всю строку (поиск ключа), и это значительно снизит производительность. Иногда это снижает производительность настолько, что движок БД решает выполнить полное сканирование вместо того, чтобы даже возиться с индексом; это зависит от количества выбранных строк.
Итак, если, удалив столбцы, вы сможете превратить это в покрывающий запрос, тогда да, это может повысить производительность. В противном случае, наверное, нет. Во всяком случае не заметно.
Быстрый пример для SQL Server 2005+ - допустим, это ваша таблица:
ID int NOT NULL IDENTITY PRIMARY KEY CLUSTERED,
Name varchar(50) NOT NULL,
Status tinyint NOT NULL
Если мы создадим этот индекс:
CREATE INDEX IX_MyTable
ON MyTable (Name)
Тогда этот запрос будет быстрым:
SELECT ID
FROM MyTable
WHERE Name = 'Aaron'
Но этот запрос будет медленным (er):
SELECT ID, Name, Status
FROM MyTable
WHERE Name = 'Aaron'
Если мы изменим индекс на покрывающий индекс, т.е.
CREATE INDEX IX_MyTable
ON MyTable (Name)
INCLUDE (Status)
Затем второй запрос снова становится быстрым, потому что механизму БД никогда не нужно читать строку.
Ограничение количества столбцов не оказывает заметного влияния на запрос. Почти всегда в кэш извлекается целая строка. Проекция происходит последней в конвейере SQL.
Проекционная часть обработки должна выполняться последней (например, после GROUP BY), поскольку она может включать создание агрегатов. Кроме того, для обработки JOIN, WHERE и ORDER BY может потребоваться много столбцов. В результирующем наборе возвращено больше столбцов, чем окончательно. Вряд ли стоит добавлять в план запроса шаг для выполнения прогнозов, чтобы хоть как-то сэкономить немного операций ввода-вывода.
Проверьте документацию по плану запроса. В плане запроса нет узла "проект". Это небольшая часть формулирования набора результатов.
Чтобы уйти от «выборки всей строки», вам нужно перейти к столбцовой («перевернутой») базе данных.
Это может зависеть от сервера, с которым вы имеете дело (и, в случае MySQL, от механизма хранения). Просто, например, есть по крайней мере один механизм хранения MySQL, который выполняет хранение по столбцам, а не по строкам, и в этом случае большее количество столбцов действительно может занять больше времени.
Другой важной возможностью было бы, если бы вы сегментировали свою таблицу, чтобы некоторые столбцы хранились на одном сервере, а другие столбцы - на другом (так называемое вертикальное разбиение). В этом случае для получения большего количества столбцов может потребоваться получение данных с разных серверов, и всегда возможно, что нагрузка несбалансирована, поэтому разные серверы имеют разное время отклика. Конечно, обычно вы пытаетесь поддерживать разумную балансировку нагрузки, поэтому это должно быть довольно необычно, но все же возможно (особенно, если, например, один из серверов обрабатывает некоторые другие данные, использование которых может отличаться от остальных).
да, если ваш запрос может быть покрыт некластеризованным индексом, это будет быстрее, так как все данные уже находятся в индексе, а базовая таблица (если у вас есть куча) или кластеризованный индекс не нужно трогать оптимизатором
Чтобы продемонстрировать то, что уже написал тванфоссон, что существует стоимость «передачи», я выполнил следующие два оператора на базе данных MSSQL 2000 из анализатора запросов.
ВЫБЕРИТЕ длину данных (текст) ИЗ syscomments
ВЫБРАТЬ текст ИЗ syscomments
Оба результата вернули 947 строк, но первый занял 5 мс, а второй 973 мс.
Кроме того, поскольку поля одинаковы, я бы не ожидал, что здесь будет учитываться индексация.