выберите * по сравнению с избранным столбцом

Если мне просто нужен 2/3 столбца, и я запрашиваю SELECT * вместо того, чтобы предоставить те столбцы в запросе Select, там снижение производительности относительно больше/меньше ввода-вывода или памяти?

Сеть наверху могла бы присутствовать, если я действительно выбираю * без потребности.

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

Если это всегда вытягивает кортеж затем, ввод-вывод наверху является тем же.

В то же время могло бы быть потребление памяти для снятия требуемых столбцов от кортежа, если это вытягивает кортеж.

Так, если это так, выберите someColumn, будет иметь больше памяти наверху, чем память выбора *

120
задан Phillip 20 January 2018 в 23:31
поделиться

7 ответов

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

Он всегда тянет за собой кортеж, потому что (во всех вендорских РСУБД, с которыми я знаком), базовая структура хранения на диске для всего (включая табличные данные) основана на определенных Страницах ввода-вывода (в SQL Server, например, каждая Страница составляет 8 килобайт). И каждое чтение или запись I/O происходит по Страницам. Т.е. каждая запись или чтение - это полная Страница данных.

Из-за этого основного структурного ограничения, следствием является то, что каждая строка данных в базе данных всегда должна находиться на одной и только одной странице. Она не может охватывать несколько страниц данных (за исключением специальных вещей, таких как блобы, где фактические данные блоба хранятся в отдельных Page-кусках, а фактический столбец строки таблицы получает только указатель...). Но эти исключения - всего лишь исключения, и обычно они не применяются, за исключением особых случаев (для особых типов данных, или определенных оптимизаций для особых обстоятельств)
. Даже в этих особых случаях, как правило, сама строка данных в таблице (которая содержит указатель на фактические данные для блоба или чего-либо еще) должна храниться на одной странице ввода-вывода...

ИСКЛЮЧЕНИЕ. Единственное место, где Select * нормально, это в подзапросе после Exists или Not Exists предикатного предложения, как в:

   Select colA, colB
   From table1 t1
   Where Exists (Select * From Table2
                 Where column = t1.colA)

EDIT: Чтобы ответить на комментарий @Mike Sherer, Да, это правда, как технически, с небольшим определением для вашего особого случая, так и эстетически. Во-первых, даже когда набор запрашиваемых столбцов является подмножеством столбцов, хранящихся в некотором индексе, процессор запроса должен получить каждый столбец, хранящийся в этом индексе, а не только те, которые запрашиваются, по тем же причинам - ВЕСЬ ввод/вывод должен выполняться в страницах, а данные индекса хранятся в страницах ввода/вывода так же, как и данные таблицы. Поэтому, если вы определите "кортеж" для индексной страницы как набор столбцов, хранящихся в индексе, утверждение все еще верно.

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

Другие причины не использовать Select * см. в Почему SELECT * считается вредным? :

28
ответ дан 24 November 2019 в 01:40
поделиться

Во время выбора SQL база данных всегда будет ссылаться на метаданные для таблицы, независимо от того, является ли это SELECT * для SELECT a, b, c ... Почему? Потому что именно здесь находится информация о структуре и расположении таблицы в системе.

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

Теперь очевидно, что метаданные БД кэшируются в системе, но их обработка еще не завершена.

Затем метаданные используются для создания плана запроса. Это также происходит каждый раз при компиляции оператора. Опять же, это работает с кешированными метаданными, но это всегда делается.

Единственный раз, когда эта обработка не выполняется, - это когда БД использует предварительно скомпилированный запрос или кэширует предыдущий запрос. Это аргумент в пользу использования параметров привязки, а не буквального SQL. «SELECT * FROM TABLE WHERE key = 1» - это другой запрос, чем «SELECT * FROM TABLE WHERE key =?» и "1" привязана к вызову.

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

Однако, если вы все еще используете диск для своей БД, основная оптимизация, выполняемая многими системами, заключается в том, чтобы полагаться на данные в индексах, а не на сами таблицы.

Если у вас есть:

CREATE TABLE customer (
    id INTEGER NOT NULL PRIMARY KEY,
    name VARCHAR(150) NOT NULL,
    city VARCHAR(30),
    state VARCHAR(30),
    zip VARCHAR(10));

CREATE INDEX k1_customer ON customer(id, name);

Затем, если вы выполните команду «ВЫБРАТЬ id, имя FROM customer WHERE id = 1», весьма вероятно, что ваша БД будет извлекать эти данные из индекса, а не из таблиц.

Почему? Он, скорее всего, в любом случае будет использовать индекс для удовлетворения запроса (в отличие от сканирования таблицы), и даже если 'name' не используется в предложении where, этот индекс по-прежнему будет лучшим вариантом для запроса.

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

Это краткое объяснение конкретного метода оптимизации, используемого некоторыми базами данных. У многих есть несколько методов оптимизации и настройки.

В конце концов, SELECT * полезен для динамических запросов, которые нужно вводить вручную, я бы никогда не использовал его для «реального кода». Идентификация отдельных столбцов дает БД больше информации, которую она может использовать для оптимизации запроса, и дает вам лучший контроль в вашем коде от изменений схемы и т. Д.

6
ответ дан 24 November 2019 в 01:40
поделиться

Я думаю, что на ваш вопрос нет точного ответа, потому что вы задумываетесь о производительности и возможностях поддержки своих приложений. Выбор столбца более эффективен, чем select * , но если вы разрабатываете ориентированную объектную систему, вам понравится использовать object.properties , и вам может понадобиться properties в любой части приложений, тогда вам нужно будет написать больше методов для получения свойств в особых ситуациях, если вы не используете select * и заполняете все свойства. Ваши приложения должны иметь хорошую производительность, используя select * , и в некоторых случаях вам понадобится использовать столбец select для повышения производительности. Тогда у вас будет лучшее из двух миров: возможность писать и поддерживать приложения и производительность, когда вам нужна производительность.

4
ответ дан 24 November 2019 в 01:40
поделиться

Есть несколько причин, по которым вы никогда (никогда) не должны (никогда) использовать SELECT * в производственном коде:

  • , поскольку вы не даете своей базе данных никаких подсказок относительно того, что вы хотите, сначала нужно будет проверить определение таблицы, чтобы определить столбцы в этой таблице. Этот поиск будет стоить некоторое время - не так много в одном запросе - но со временем он складывается

  • , если вам нужно только 2/3 столбца, вы выбираете 1/3 слишком большого количества данных, которые необходимо получить из диск и отправляется по сети

  • , если вы начинаете полагаться на определенные аспекты данных, например порядок возвращаемых столбцов, вы можете получить неприятный сюрприз после реорганизации таблицы и добавления новых столбцов (или удаления существующих)

  • в SQL Server (не уверен в других базах данных), если вам нужно подмножество столбцов , всегда есть вероятность, что некластеризованный индекс может покрывать этот запрос (содержать все необходимые столбцы). Используя SELECT * , вы отказываетесь от этой возможности с самого начала. В этом конкретном случае данные будут извлекаться из индексных страниц (если они содержат все необходимые столбцы), и, таким образом, накладные расходы на дисковый ввод-вывод и памяти будут намного меньше по сравнению с выполнением SELECT * .... запрос.

Да, сначала требуется немного больше набора текста (такие инструменты, как SQL Prompt для SQL Server, даже помогут вам в этом) - но это действительно тот случай, когда есть правило без каких-либо исключений: никогда используйте SELECT * в своем производственном коде. НИКОГДА.

108
ответ дан 24 November 2019 в 01:40
поделиться

Это сразу заставляет меня вспомнить таблицу, которую я использовал, содержащую столбец типа blob; он обычно содержал изображение JPEG размером в несколько Мб.

Излишне говорить, что я не ВЫБИРАЛ этот столбец, если он не был мне действительно нужен. То, что эти данные плавали повсюду - особенно когда я выбирал несколько строк - было просто неприятно.

Однако я признаю, что в других случаях я обычно запрашиваю все столбцы в таблице.

6
ответ дан 24 November 2019 в 01:40
поделиться

Если вы не храните большие двоичные объекты, производительность не имеет значения. Основная причина не использовать SELECT * заключается в том, что если вы используете возвращаемые строки как кортежи, столбцы возвращаются в том порядке, который указан в схеме, и если это изменится, вам придется исправить весь свой код.

С другой стороны, если вы используете доступ в стиле словаря, то не имеет значения, в каком порядке возвращаются столбцы, потому что вы всегда обращаетесь к ним по имени.

7
ответ дан 24 November 2019 в 01:40
поделиться

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

[править]: имел в виду доступ. Глупый мозг все еще просыпается.

20
ответ дан 24 November 2019 в 01:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: