Что причина не состоит в том, чтобы использовать выбор *?

Когда вы объявляете ссылочную переменную (т. е. объект), вы действительно создаете указатель на объект. Рассмотрим следующий код, в котором вы объявляете переменную примитивного типа int:

int x;
x = 10;

В этом примере переменная x является int, и Java инициализирует ее для 0. Когда вы назначаете его 10 во второй строке, ваше значение 10 записывается в ячейку памяти, на которую указывает x.

Но когда вы пытаетесь объявить ссылочный тип, произойдет что-то другое. Возьмите следующий код:

Integer num;
num = new Integer(10);

Первая строка объявляет переменную с именем num, но она не содержит примитивного значения. Вместо этого он содержит указатель (потому что тип Integer является ссылочным типом). Поскольку вы еще не указали, что указать на Java, он устанавливает значение null, что означает «Я ничего не указываю».

Во второй строке ключевое слово new используется для создания экземпляра (или создания ) объекту типа Integer и переменной указателя num присваивается этот объект. Теперь вы можете ссылаться на объект, используя оператор разыменования . (точка).

Exception, о котором вы просили, возникает, когда вы объявляете переменную, но не создавали объект. Если вы попытаетесь разыменовать num. Перед созданием объекта вы получите NullPointerException. В самых тривиальных случаях компилятор поймает проблему и сообщит вам, что «num не может быть инициализирован», но иногда вы пишете код, который непосредственно не создает объект.

Например, вы можете имеют следующий метод:

public void doSomething(SomeObject obj) {
   //do something to obj
}

В этом случае вы не создаете объект obj, скорее предполагая, что он был создан до вызова метода doSomething. К сожалению, этот метод можно вызвать следующим образом:

doSomething(null);

В этом случае obj имеет значение null. Если метод предназначен для того, чтобы что-то сделать для переданного объекта, целесообразно бросить NullPointerException, потому что это ошибка программиста, и программисту понадобится эта информация для целей отладки.

Альтернативно, там могут быть случаи, когда цель метода заключается не только в том, чтобы работать с переданным в объекте, и поэтому нулевой параметр может быть приемлемым. В этом случае вам нужно будет проверить нулевой параметр и вести себя по-другому. Вы также должны объяснить это в документации. Например, doSomething может быть записано как:

/**
  * @param obj An optional foo for ____. May be null, in which case 
  *  the result will be ____.
  */
public void doSomething(SomeObject obj) {
    if(obj != null) {
       //do something
    } else {
       //do something else
    }
}

Наконец, Как определить исключение & amp; причина использования Трассировки стека

135
задан Community 23 May 2017 в 11:47
поделиться

18 ответов

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

при использовании выбора *, Вы, лишают возможности представлять, поэтому Вы не пишете ясный & простой код и Вы идете вразрез с духом кавычки. select * антишаблон.

<час>

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

  1. при определении столбцов в SQL-операторе механизм выполнения SQL будет ошибка, если тот столбец будет удален из таблицы, и запрос выполняется.
  2. можно более легко отсканировать код, где тот столбец используется.
  3. необходимо всегда писать запросы для возвращения наименьшего количества объема информации.
  4. , Поскольку другие упоминают, используете ли Вы порядковый доступ столбца, Вы никогда не должны использовать выбор *
  5. , Если Ваши таблицы соединений SQL-оператора, выберите *, дает Вам всем столбцы от всех таблиц в соединении

, заключение является тем использованием select *...

  1. столбцы, используемые приложением, непрозрачны
  2. , DBA и их профилировщики запроса не может помочь низкой производительности Вашего приложения
  3. , код является более хрупким, когда изменения происходят
  4. , Ваша база данных и сеть страдают, потому что они возвращают слишком много данных (ввод-вывод)
  5. , оптимизация Механизма базы данных минимальна, поскольку Вы возвращаете все данные, независимо (логичные).
<час>

Запись, корректная, SQL так же легок как запись Select *. Таким образом, настоящий ленивый человек пишет надлежащий SQL, потому что они не хотят пересматривать код и пытаться помнить то, что они делали, когда они сделали это. Они не хотят объяснять DBA о каждом бите кода. Они не хотят объяснять их клиентам почему выполнение приложения как собака.

167
ответ дан 23 November 2019 в 23:44
поделиться

Хорошо, когда Вы делаете exists(select * ...), так как это никогда не расширяется. Иначе действительно только полезно при исследовании таблиц с временным выбором statments или если Вам определили CTE выше, и Вы хотите каждый столбец, не вводя их всех снова.

1
ответ дан 23 November 2019 в 23:44
поделиться

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

1
ответ дан 23 November 2019 в 23:44
поделиться

Для ответа Вы подвергаете сомнению непосредственно: не используйте "ВЫБОР *", когда он сделает Ваш код большим количеством fragle к изменениям в базовых таблицах. Ваш код должен повредиться только, когда изменение внесено в таблицу, которая непосредственно влияет на requirments Вашей программы.

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

1
ответ дан 23 November 2019 в 23:44
поделиться

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

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

1
ответ дан 23 November 2019 в 23:44
поделиться

Я не использую ВЫБОР * просто, потому что хорошо видеть и знать, какие поля я получаю.

1
ответ дан 23 November 2019 в 23:44
поделиться

Это делает Ваш код более неоднозначным и более трудным поддержать; потому что Вы добавляете дополнительные неиспользованные данные к домену, и это не ясно, который Вы предназначили и который нет. (Это также предполагает, что Вы не могли бы знать, или уход.)

1
ответ дан 23 November 2019 в 23:44
поделиться

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

Так в основном это - вопрос пригодности для обслуживания! Если Вы не используете * селектор, Вы не должны будете волноваться о своих запросах.

1
ответ дан 23 November 2019 в 23:44
поделиться

Я понимаю, куда Вы идете относительно преждевременной оптимизации, но который действительно только переходит к точке. Намерение состоит в том, чтобы избежать ненужный оптимизация в начале. Действительно ли Ваши таблицы неиндексируемы? Вы использовали бы nvarchar (4000) для хранения почтового индекса?

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

2
ответ дан 23 November 2019 в 23:44
поделиться

Я на самом деле заметил странное поведение, когда я использовал select * в представлениях в SQL Server 2005.

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

IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[starTest]') AND type in (N'U'))
DROP TABLE [dbo].[starTest]
CREATE TABLE [dbo].[starTest](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [A] [varchar](50) NULL,
    [B] [varchar](50) NULL,
    [C] [varchar](50) NULL
) ON [PRIMARY]

GO

insert into dbo.starTest
select 'a1','b1','c1'
union all select 'a2','b2','c2'
union all select 'a3','b3','c3'

go
IF  EXISTS (SELECT * FROM sys.views WHERE object_id = OBJECT_ID(N'[dbo].[vStartest]'))
DROP VIEW [dbo].[vStartest]
go
create view dbo.vStartest as
select * from dbo.starTest
go

go
IF  EXISTS (SELECT * FROM sys.views WHERE object_id = OBJECT_ID(N'[dbo].[vExplicittest]'))
DROP VIEW [dbo].[vExplicittest]
go
create view dbo.[vExplicittest] as
select a,b,c from dbo.starTest
go


select a,b,c from dbo.vStartest
select a,b,c from dbo.vExplicitTest

IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[starTest]') AND type in (N'U'))
DROP TABLE [dbo].[starTest]
CREATE TABLE [dbo].[starTest](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [A] [varchar](50) NULL,
    [B] [varchar](50) NULL,
    [D] [varchar](50) NULL,
    [C] [varchar](50) NULL
) ON [PRIMARY]

GO

insert into dbo.starTest
select 'a1','b1','d1','c1'
union all select 'a2','b2','d2','c2'
union all select 'a3','b3','d3','c3'

select a,b,c from dbo.vStartest
select a,b,c from dbo.vExplicittest

Сравнивают результаты последних 2 избранных операторов. Я верю тому, что Вы будете видеть, результат Выбор * столбцы ссылки индексом вместо имени.

при восстановлении представления, оно будет хорошо работать снова.

РЕДАКТИРОВАНИЕ

я добавил отдельный вопрос, * “select * от table” по сравнению с “select колой, colB, и т.д. от table” интересного поведения в SQL Server 2005 * для изучения того поведения более подробно.

3
ответ дан 23 November 2019 в 23:44
поделиться

Вы могли бы присоединиться к двум таблицам и использовать столбец A от второй таблицы. Если Вы позже добавите столбец A к первой таблице (с тем же именем, но возможно другим значением), то Вы, скорее всего, получите значения от первой таблицы а не второй как ранее. Этого не произойдет при явном определении столбцов, Вы хотите выбрать.

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

2
ответ дан 23 November 2019 в 23:44
поделиться

Одна основная причина состоит в том, что, если Вы когда-нибудь добавляете/удаляете столбцы от своей таблицы, любой запрос/процедура, который делает ВЫБОР * вызов, будет теперь получать более или менее столбцы данных, чем ожидалось.

23
ответ дан 23 November 2019 в 23:44
поделиться
  1. окольным способом Вы нарушаете правило модульного принципа об использовании строгого ввода по мере возможности. Явный почти универсально лучше.

  2. , Даже если Вам теперь нужен каждый столбец в таблице, больше могло бы быть добавлено позже, который будет раскрыт каждый раз, когда Вы выполняете запрос и могли повредить производительность. Это повреждает производительность, потому что

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

, Когда использовать выбор *

, Когда Вам явно НУЖЕН каждый столбец в таблице, в противоположность необходимости в каждом столбце в таблице THAT EXISTED AT THE TIME YOU WROTE THE QUERY. Например, если бы писали приложение управления DB, которое должно было отобразить все содержание таблицы (независимо от того, что они, оказалось, были), то Вы могли бы использовать тот подход.

16
ответ дан 23 November 2019 в 23:44
поделиться

Если Ваше приложение получит данные с ВЫБОРОМ *, и структура таблицы в базе данных изменяется (скажите, что столбец удален), то Ваше приложение перестанет работать в каждом месте, что Вы ссылаетесь на недостающее поле. Если Вы вместо этого будете включать все столбцы в свой запрос, Вы, то приложение прервет (надо надеяться), одно место, где Вы первоначально получаете данные, делая фиксацию легче.

Однако существует много ситуаций, в которых ВЫБОР * желателен. Каждый - ситуация, что я встречаюсь все время, где я должен копировать всю таблицу в другую базу данных (как SQL Server к DB2, например). Другой - приложение, записанное для отображения таблиц в общем (т.е. без любого ведома какой-то конкретной таблицы).

7
ответ дан 23 November 2019 в 23:44
поделиться

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

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

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

42
ответ дан 23 November 2019 в 23:44
поделиться

Существует несколько причин:

  1. , Если число столбцов в базе данных изменяется и Ваше приложение ожидает там быть определенным числом...
  2. , Если порядок столбцов в базе данных изменяется и Ваше приложение ожидает, что они будут в определенном порядке...
  3. Память наверху. 8 ненужных столбцов INTEGER добавили бы 32 байта потраченной впустую памяти. Это не походит на много, но это для каждого запроса, и ЦЕЛОЕ ЧИСЛО является одним из маленьких типов столбца... дополнительные столбцы, более вероятно, будут VARCHAR или Столбцами текста, который складывает более быстрый.
  4. Сеть наверху. Связанный с памятью наверху: если я, запросы выпуска 30,000 и имеют 8 ненужных столбцов INTEGER, я потратил впустую 960 КБ пропускной способности. VARCHAR и Столбцы текста, вероятно, будут значительно больше.

Примечание: Я выбрал INTEGER в вышеупомянутом примере, потому что у них есть фиксированный размер 4 байтов.

12
ответ дан 23 November 2019 в 23:44
поделиться

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

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

1
ответ дан 23 November 2019 в 23:44
поделиться

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

2
ответ дан 23 November 2019 в 23:44
поделиться
Другие вопросы по тегам:

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