Лучший способ понять сложные SQL-операторы?

Неустранимая ошибка: допустимый размер памяти из XXX байт исчерпан (пытался выделить XXX байты)

Недостаточно памяти для запуска вашего скрипта. PHP достиг предела памяти и перестает его выполнять. Эта ошибка является фатальной, сценарий останавливается. Значение предела памяти можно настроить либо в файле php.ini, либо с помощью ini_set('memory_limit', '128 M'); в скрипте (который перезапишет значение, определенное в php.ini). Цель ограничения памяти заключается в том, чтобы не допустить, чтобы один скрипт PHP собирал всю доступную память и приводил к остановке всего веб-сервера.

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

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

Вопросы, относящиеся:

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

14 ответов

Когда я смотрю на сложный бит кода SQL, это - то, что я делаю.

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

Понимание соединений очень важно для понимания сложного SQL. Для каждого соединения я спрашиваю меня, почему это здесь? Существует четыре основных причины. Вам нужен столбец для выбора, Вам нужно поле для, где пункт, Вам нужно соединение как мост к третьей таблице, или необходимо соединить с таблицей для фильтрации записей (таких как получение деталей о клиенте, у кого есть заказы, но не необходимость в подробных сведениях о заказе, это может часто добиваться большего успеха с, ЕСЛИ СУЩЕСТВУЕТ где пункт). Если это - левое или правое соединение (я склонен переписывать так, все - левое соединение, которое делает жизнь более простой.), я рассматриваю, работало ли внутреннее объединение. Почему мне нужно левое соединение? Если я не буду знать ответ, я буду выполнять его оба пути и видеть то, что различие в данных. Если будут полученные таблицы, я посмотрю на тех сначала (работающий просто, что часть выбора для наблюдения то, что результат) для понимания, почему это там. Если будут подзапросы, я попытаюсь понять их и если они будут медленными, то попытается преобразовать в полученную таблицу вместо этого, поскольку те часто намного быстрее.

Затем, я смотрю эти where пункты. Это - одно место, где прочная основа в Вашей конкретной базе данных пригодится. Например, я знаю в своих базах данных, какие случаи я, возможно, должен был бы видеть только почтовый адрес и какие случаи я, возможно, должен был бы видеть другие адреса. Это помогает мне знать, отсутствует ли что-то в где пункт. Иначе я рассматриваю каждый объект в where пункт и фигура, почему это должно было бы быть там, тогда я рассматриваю, существует ли что-нибудь отсутствующее, который должен быть там. После просмотра его я рассматриваю, могу ли я внести изменения для создания запроса sargable.

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

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

, Если текущий запрос фильтрует неправильно, я удалю биты его для обнаружения то, что избавляется от записей, которые я не хочу или добавляющие, которые я не хочу. Часто Вы будете находить, что соединение является тем многим, и Вам нужен тот к одному (используйте полученную таблицу в этом случае!) или Вы найдете, что некоторая информация, что Вы думаете, что Вам нужно в where, пункт не верен для всех данных, в которых Вы нуждаетесь или что некоторая часть where пункт отсутствует. Это помогает иметь все поля в where пункт (если они уже не были в выборе) в выборе в то время, когда Вы делаете это. Это может даже помочь показать все поля из всех объединяемых таблиц и действительно посмотреть на данные. Когда я делаю это, я часто добавляю маленький бит к, где пункт для захвата просто некоторых записей, которые я имею, который не должен быть там, а не все записи.

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

40
ответ дан HLGEM 26 November 2019 в 22:44
поделиться

Я разламываю его на меньшие запросы (вот почему, мне нравятся подзапросы больше, чем СОЕДИНЕНИЯ)

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

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

ИЗБРАННЫЙ T1. Идентификатор ОТ TABLE1 T1, ГДЕ T1. ДАТА = (ВЫБИРАЮТ МАКСА (T11. ДАТА) ОТ TABLE1 T11, ГДЕ (T1. ОБЛАСТЬ = T11. ОБЛАСТЬ))

Аплодисменты

-1
ответ дан Richard Haven 26 November 2019 в 22:44
поделиться

При использовании PostgreSQL инкапсуляция представления замечательна для этого.

0
ответ дан Kev 26 November 2019 в 22:44
поделиться

Использование CTEs или полученных таблиц (в SQL MS, по крайней мере) может быть полезным для форматирования SQL-оператора, не разделяя его на отдельные запросы с помощью временных таблиц для "присоединений" к ним.

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

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

0
ответ дан gbn 26 November 2019 в 22:44
поделиться

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

предположим, например, что у Вас есть таблица для Книг и таблица за Цены. Таблица Prices может иметь многократные въезды для каждой книги (так как цена может измениться).

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

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

, Как только Вы приобретаете навык его, сложные запросы становятся легче проанализировать.

1
ответ дан Michael Haren 26 November 2019 в 22:44
поделиться

Вы делаете то, что я делаю. Мой первый инструмент для того, чтобы сделать запрос понятным является хорошей визуальной организацией, которую люди в вопросе, на который Вы ссылаетесь, главным образом делают и тестируют в управляемых блоках с помощью ПРЕДЕЛЬНЫХ пунктов. Если несвязанные подзапросы включены, они могут быть выполнены отдельно, конечно. Если существует чудодейственное средство, тем не менее, я не знаю об этом.

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

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

Пробел очень важен. Запрос, который выглядит невероятно сложным, может выглядеть почти упрощенным, когда надлежащий пробел присутствует.

относительно соединений... Ну, я сожалею, но я не могу быть очень услужливым здесь, потому что мой ответ - то, что лучший способ понять конкретное соединение состоит в том, чтобы понять, как соединения работают в целом. Каждый тип соединения служит очень определенной цели и если Вы знаете, как они работают, не должно действительно быть большой части различия от присоединения x к y, x к y к z или X и Y к a и b.

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

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

2
ответ дан Gene Roberts 26 November 2019 в 22:44
поделиться

Другой importan является синтаксисом соединения стандарта использования:

SELECT A 
  FROM B
  JOIN C ON B.ID = C.ID
 WHERE C.X = 1

Вместо

SELECT A 
  FROM B
     , C 
 WHERE B.ID = C.ID 
   AND C.X = 1
2
ответ дан FerranB 26 November 2019 в 22:44
поделиться

Я предполагаю, что все это зависит от опыта. Я не нашел запросы в этом вопросами быть очень сложным, возможно, так как большинство запросов, которые я выполняю, более сложно, чем те.

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

2
ответ дан Eran Galperin 26 November 2019 в 22:44
поделиться

форматирование помогает, но понимающий теорию множеств и следовательно, реляционная теория, помогает еще больше.

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

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

, понимают сначала, что происходит с каждой таблицей, и как к таблицам присоединяются

5
ответ дан Steven A. Lowe 26 November 2019 в 22:44
поделиться

Добавление отступа и комментарии помогают много. Самой ценной вещью, с которой я столкнулся, является оператор WITH. Это находится в Oracle и имеет дело с рефакторингом подзапроса. Это позволяет Вам повреждать выполнение больших запросов в ряд по-видимому меньших. Каждый просто немного более управляемый.

Вот пример

WITH 
ssnInfo AS
(
    SELECT SSN, 
           UPPER(LAST_NAME), 
           UPPER(FIRST_NAME), 
           TAXABLE_INCOME,          
           CHARITABLE_DONATIONS
    FROM IRS_MASTER_FILE
    WHERE STATE = 'MN'                 AND -- limit to in-state
          TAXABLE_INCOME > 250000      AND -- is rich 
          CHARITABLE_DONATIONS > 5000      -- might donate too

),
doltishApplicants AS
(
    SELECT SSN, 
           SAT_SCORE,
           SUBMISSION_DATE
    FROM COLLEGE_ADMISSIONS
    WHERE SAT_SCORE < 100          -- About as smart as a Moose.
),
todaysAdmissions AS
(
    SELECT doltishApplicants.SSN, 
           TRUNC(SUBMISSION_DATE)  SUBMIT_DATE, 
           LAST_NAME, FIRST_NAME, 
           TAXABLE_INCOME
    FROM ssnInfo,
         doltishApplicants
    WHERE ssnInfo.SSN = doltishApplicants.SSN

)
SELECT 'Dear ' || FIRST_NAME || 
       ' your admission to WhatsaMattaU has been accepted.'
FROM todaysAdmissions
WHERE SUBMIT_DATE = TRUNC(SYSDATE)    -- For stuff received today only
;

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

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

На работе, наша группа разработки обычно находит их легче поддержать, и часто быстрее.

8
ответ дан EvilTeach 26 November 2019 в 22:44
поделиться

Вот процедура для следования для распутывания запроса.

  1. Первый я форматирую SQL.
  2. Тогда я комментирую все части SQL кроме базовых деталей самой основной или самой важной таблицы для ответа на вопрос.
  3. Тогда я начну не комментировать соединения, выбирать столбцы, группировки, заказывать поля, & фильтры для изолирования различных частей запроса для наблюдения, что происходит. Или выделенное выполнение работает в некоторых инструментах.
  4. Подзапросы могут обычно выполняться независимо.

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

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

Главным образом это - просто опыт и надлежащее расположение с отступом.

9
ответ дан Stephane Grenier 26 November 2019 в 22:44
поделиться

Они могут быть некоторыми полезными подсказками..

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

, Например:

select ID, Description, Status from ABC where Status = 1 OR Status = 3

мог быть лучше записан как:

select 
  ID,
  Description,
  Status
from ABC
where
  Status = 1 OR
  Status = 3

с более сложным запросом, Вы видели бы намного большее преимущество.

17
ответ дан Kon 26 November 2019 в 22:44
поделиться
Другие вопросы по тегам:

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