Выберите правильное утверждение, какими свойствами обладает файл

Обновлено: 06.07.2024

Spring Boot включает в себя дополнительный набор инструментов, которые могут сделать процесс разработки приложений более приятным. Модуль spring-boot-devtools можно включить в любой проект, чтобы обеспечить дополнительные функции во время разработки. Чтобы включить поддержку devtools, просто добавьте зависимость модуля в свою сборку:

Инструменты разработчика автоматически отключаются при запуске полностью упакованного приложения. Если ваше приложение запускается с помощью java -jar или если оно запускается с помощью специального загрузчика классов, то оно считается «рабочим приложением». Пометка зависимости как необязательной в Maven или использование compileOnly в Gradle — это наилучшая практика, которая предотвращает транзитивное применение инструментов разработки к другим модулям, использующим ваш проект.

По умолчанию переупакованные архивы не содержат инструментов разработки. Если вы хотите использовать определенную удаленную функцию devtools, вам нужно отключить свойство сборки excludeDevtools, чтобы включить ее. Свойство поддерживается подключаемыми модулями Maven и Gradle.

20.1 Значения свойства по умолчанию

Хотя кэширование очень полезно в производственной среде, оно может быть контрпродуктивным во время разработки, не позволяя вам увидеть изменения, которые вы только что внесли в свое приложение. По этой причине spring-boot-devtools по умолчанию отключит эти параметры кэширования.

Параметры кэша обычно настраиваются в файле application.properties. Например, Thymeleaf предлагает свойство spring.thymeleaf.cache. Вместо того, чтобы задавать эти свойства вручную, модуль spring-boot-devtools автоматически применит разумную конфигурацию времени разработки.

Полный список применяемых свойств см. в DevToolsPropertyDefaultsPostProcessor.

20.2 Автоматический перезапуск

Приложения, использующие spring-boot-devtools, автоматически перезапускаются при изменении файлов в пути к классам. Это может быть полезной функцией при работе в среде IDE, поскольку она обеспечивает очень быструю обратную связь для изменений кода. По умолчанию любая запись в пути к классам, указывающая на папку, будет отслеживаться на предмет изменений. Обратите внимание, что для некоторых ресурсов, таких как статические ресурсы и шаблоны представлений, перезапуск приложения не требуется.

Запуск перезагрузки

Поскольку DevTools отслеживает ресурсы пути к классам, единственный способ инициировать перезапуск — обновить путь к классам. Способ, которым вы вызываете обновление пути к классам, зависит от используемой вами IDE. В Eclipse сохранение измененного файла приведет к обновлению пути к классам и запуску перезапуска. В IntelliJ IDEA сборка проекта ( Build -> Build Project ) будет иметь тот же эффект.

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

Автоматический перезапуск работает очень хорошо при использовании LiveReload. Подробнее см. ниже. Если вы используете JRebel, автоматический перезапуск будет отключен в пользу динамической перезагрузки класса. Другие функции инструментов разработки (такие как LiveReload и переопределение свойств) по-прежнему можно использовать.

DevTools использует обработчик завершения работы контекста приложения, чтобы закрыть его во время перезапуска. Это не будет работать правильно, если вы отключили перехватчик выключения ( SpringApplication.setRegisterShutdownHook(false) ).

При принятии решения о том, должна ли запись в пути к классам запускать перезагрузку при ее изменении, DevTools автоматически игнорирует проекты с именами spring-boot , spring-boot-devtools , spring-boot-autoconfigure , spring-boot-actuator и spring-boot. -стартер .

DevTools необходимо настроить ResourceLoader, используемый ApplicationContext: если ваше приложение уже предоставляет его, он будет упакован. Прямое переопределение метода getResource в ApplicationContext не поддерживается.

Перезапустить или перезагрузить

Технология перезапуска, предоставляемая Spring Boot, работает с использованием двух загрузчиков классов. Неизменяемые классы (например, из сторонних jar-файлов) загружаются в базовый загрузчик классов. Классы, которые вы активно разрабатываете, загружаются в restart загрузчик классов. Когда приложение перезапускается, загрузчик классов restart удаляется и создается новый. Такой подход означает, что перезапуск приложения обычно происходит намного быстрее, чем «холодный запуск», поскольку базовый загрузчик классов уже доступен и заполнен.

Если вы обнаружите, что перезапуск ваших приложений происходит недостаточно быстро, или у вас возникли проблемы с загрузкой классов, вы можете рассмотреть возможность перезагрузки таких технологий, как JRebel, из ZeroTurnaround. Они работают, переписывая классы по мере их загрузки, чтобы сделать их более удобными для перезагрузки. Spring Loaded предоставляет еще один вариант, однако он не поддерживает столько фреймворков и не поддерживается на коммерческой основе.

20.2.1 Исключение ресурсов

Некоторые ресурсы не обязательно должны инициировать перезагрузку при изменении. Например, шаблоны Thymeleaf можно просто редактировать на месте. По умолчанию изменение ресурсов в /META-INF/maven , /META-INF/resources , /resources , /static , /public или /templates не приведет к перезагрузке, но вызовет перезагрузку в реальном времени. Если вы хотите настроить эти исключения, вы можете использовать свойство spring.devtools.restart.exclude. Например, чтобы исключить только /static и /public, вы должны установить следующее:

если вы хотите сохранить эти значения по умолчанию и добавить дополнительные исключения, вместо этого используйте свойство spring.devtools.restart.additional-exclude.

20.2.2 Просмотр дополнительных путей

Вы можете захотеть, чтобы ваше приложение перезапускалось или перезагружалось, когда вы вносите изменения в файлы, которые не находятся в пути к классам. Для этого используйте свойство spring.devtools.restart.additional-paths, чтобы настроить дополнительные пути для отслеживания изменений. Вы можете использовать свойство spring.devtools.restart.exclude, описанное выше, чтобы управлять тем, будут ли изменения в дополнительных путях вызывать полный перезапуск или только динамическую перезагрузку.

20.2.3 Отключение перезагрузки

Если вы не хотите использовать функцию перезапуска, вы можете отключить ее с помощью свойства spring.devtools.restart.enabled. В большинстве случаев вы можете установить это в своем application.properties (это по-прежнему будет инициализировать перезапуск загрузчика классов, но он не будет отслеживать изменения файлов).

20.2.4 Использование файла триггера

Если вы работаете с интегрированной средой разработки, которая постоянно компилирует измененные файлы, вы можете предпочесть запускать перезапуски только в определенное время. Для этого вы можете использовать «файл триггера», который представляет собой специальный файл, который необходимо изменить, если вы действительно хотите запустить проверку перезапуска. Изменение файла только запускает проверку, а перезапуск произойдет только в том случае, если Devtools обнаружит, что ему нужно что-то сделать. Файл триггера можно обновить вручную или с помощью подключаемого модуля IDE.

Чтобы использовать файл триггера, используйте свойство spring.devtools.restart.trigger-file.

Возможно, вы захотите установить spring.devtools.restart.trigger-file в качестве глобальной настройки, чтобы все ваши проекты вели себя одинаково.

20.2.5 Настройка перезапуска загрузчика классов

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

По умолчанию любой открытый проект в вашей среде IDE будет загружен с использованием загрузчика классов «restart», а любой обычный файл .jar будет загружен с использованием «базового» загрузчика классов. Если вы работаете над проектом, состоящим из нескольких модулей, и не каждый модуль импортирован в вашу среду IDE, вам может потребоваться настройка. Для этого вы можете создать файл META-INF/spring-devtools.properties.

Файл spring-devtools.properties может содержать файл restart.exclude. и перезапустите.include. префиксные свойства. Включаемые элементы — это элементы, которые должны быть загружены в «перезапущенный» загрузчик классов, а исключающие элементы — это элементы, которые должны быть помещены в «базовый» загрузчик классов. Значением свойства является шаблон регулярного выражения, который будет применяться к пути к классам.

Все ключи свойств должны быть уникальными. Пока свойство начинается с restart.include. или перезапустить.исключить. это будет рассмотрено.

Будут загружены все META-INF/spring-devtools.properties из пути к классам. Вы можете упаковать файлы внутри своего проекта или в библиотеках, которые использует проект.

20.2.6 Известные ограничения

Функция перезапуска плохо работает с объектами, десериализованными с помощью стандартного ObjectInputStream . Если вам нужно десериализовать данные, вам может понадобиться использовать Spring ConfigurableObjectInputStream в сочетании с Thread.currentThread().getContextClassLoader() .

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

20.3 LiveReload

Если вы не хотите запускать сервер LiveReload во время работы вашего приложения, вы можете установить для свойства spring.devtools.livereload.enabled значение false .

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

20.4 Глобальные настройки

Вы можете настроить глобальные параметры devtools, добавив файл с именем .spring-boot-devtools.properties в свою папку $HOME (обратите внимание, что имя файла начинается с «.»). Любые свойства, добавленные в этот файл, будут применяться ко всем приложениям Spring Boot на вашем компьютере, которые используют инструменты разработки. Например, чтобы настроить перезапуск на постоянное использование файла триггера, вы должны добавить следующее:

~/.spring-boot-devtools.properties.

20.5 Удаленные приложения

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

Затем вам нужно установить свойство spring.devtools.remote.secret, например:

Включение spring-boot-devtools в удаленном приложении представляет собой угрозу безопасности. Вы никогда не должны включать поддержку в рабочем развертывании.

Удаленная поддержка инструментов разработки состоит из двух частей. есть конечная точка на стороне сервера, которая принимает соединения, и клиентское приложение, которое вы запускаете в своей среде IDE. Серверный компонент автоматически включается при установке свойства spring.devtools.remote.secret. Клиентский компонент необходимо запускать вручную.

20.5.1 Запуск удаленного клиентского приложения

Удаленное клиентское приложение предназначено для запуска из среды IDE. Вам нужно запустить org.springframework.boot.devtools.RemoteSpringApplication, используя тот же путь к классам, что и удаленный проект, к которому вы подключаетесь. Аргумент non-option, передаваемый приложению, должен быть удаленным URL-адресом, к которому вы подключаетесь.

Например, если вы используете Eclipse или STS и у вас есть проект с именем my-app, который вы развернули в Cloud Foundry, вы должны сделать следующее:

Запущенный удаленный клиент будет выглядеть следующим образом:

Поскольку удаленный клиент использует тот же путь к классам, что и реальное приложение, он может напрямую считывать свойства приложения. Вот как свойство spring.devtools.remote.secret считывается и передается на сервер для аутентификации.

Если вам нужно использовать прокси для доступа к удаленному приложению, настройте свойства spring.devtools.remote.proxy.host и spring.devtools.remote.proxy.port.

20.5.2 Удаленное обновление

Удаленный клиент будет отслеживать изменения в пути к классам вашего приложения так же, как и при локальном перезапуске. Любой обновленный ресурс будет передан удаленному приложению и (при необходимости) инициирует перезапуск. Это может быть очень полезно, если вы повторяете функцию, которая использует облачную службу, которой у вас нет локально. Как правило, удаленные обновления и перезапуски выполняются намного быстрее, чем полный цикл восстановления и развертывания.

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

20.5.3 Туннель удаленной отладки

Удаленная отладка Java полезна при диагностике проблем в удаленном приложении. К сожалению, не всегда возможно включить удаленную отладку, когда ваше приложение развернуто за пределами вашего центра обработки данных. Удаленная отладка также может быть сложной в настройке, если вы используете технологию на основе контейнеров, такую ​​как Docker.

Необходимо убедиться, что удаленное приложение запущено с включенной удаленной отладкой. Часто этого можно добиться, настроив JAVA_OPTS. Например, с помощью Cloud Foundry вы можете добавить в файл manifest.yml следующее:

Обратите внимание, что вам не нужно передавать параметр address=NNNN в -Xrunjdwp . Если опустить, Java просто выберет случайный свободный порт.

Отладка удаленной службы через Интернет может быть медленной, и вам может потребоваться увеличить время ожидания в вашей среде IDE. Например, в Eclipse вы можете выбрать Java → Отладка в настройках…​ и изменить время ожидания отладчика (мс) на более подходящее значение (60000 хорошо работает в большинстве ситуаций).

При использовании туннеля удаленной отладки с IntelliJ IDEA все точки останова должны быть настроены на приостановку потока, а не виртуальной машины. По умолчанию точки останова в IntelliJ IDEA приостанавливают всю виртуальную машину, а не только поток, достигший точки останова. Это имеет нежелательный побочный эффект приостановки потока, управляющего туннелем удаленной отладки, что приводит к зависанию сеанса отладки. При использовании туннеля удаленной отладки с IntelliJ IDEA все точки останова должны быть настроены на приостановку потока, а не виртуальной машины. Дополнительные сведения см. в документе IDEA-165769.

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

  1. Что из следующего является допустимым синтаксисом JSP для вывода значения i. Выберите один правильный ответ
<р>2. JSP-странице с именем test.jsp передается имя параметра в URL-адресе с помощью

  1. Программа печатает «Добро пожаловать, Джон»
  2. Программа выдает синтаксическую ошибку из-за оператора
  3. Программа выдает синтаксическую ошибку из-за оператора
  4. Программа выдает синтаксическую ошибку из-за оператора
<р>3. Что из следующего правильно представляет следующий оператор JSP. Выберите один правильный ответ.

<р>4. Что из следующего правильно представляет следующий оператор JSP. Выберите один правильный ответ.

<р>5.Что печатается, когда следующий код JSP вызывается в браузере. Выберите один правильный ответ.

  1. В зависимости от возвращаемого значения random браузер напечатает приветствие или привет.
  2. Строка hello всегда будет напечатана.
  3. Строка hi всегда будет напечатана.
  4. Файл JSP не будет скомпилирован.
<р>6. Какие из следующих правильны. Выберите один правильный ответ.

<р>7. Что печатается при компиляции следующего. Выберите один правильный ответ.

<р>8. Какие из следующих переменных JSP недоступны в выражении JSP. Выберите один правильный ответ.

<р>9. Бин со свойством color загружается с помощью следующего оператора

      Какой из следующих операторов может быть использован для печати значения свойства цвета компонента. Выберите один правильный ответ.
    <р>10. Бин со свойством color загружается с помощью следующего оператора

        Какой из следующих операторов может использоваться для установки свойства цвета компонента. Выберите один правильный ответ.
      <р>11. Бин со свойством color загружается с помощью следующего оператора

          Что происходит, когда выполняется следующий оператор. Выберите один правильный ответ.
        1. Это неправильный синтаксис, который приведет к ошибке компиляции. Должно быть определено либо значение, либо параметр.
        2. Все свойства фруктового компонента инициализируются значением null.
        3. Всем свойствам фруктового боба присваиваются значения входных параметров JSP-страницы с таким же именем.
        4. Все свойства фруктового компонента инициализируются значением *.
        <р>12. Верно или ложно следующее утверждение. Если атрибут isThreadSafe директивы страницы имеет значение false, то сгенерированный сервлет реализует интерфейс SingleThreadModel.

        <р>13. Что из следующего представляет правильный синтаксис для usebean. Выберите два правильных ответа.

        <р>14. Назовите значение по умолчанию для атрибута области .

        <р>15. Какие из следующих утверждений верны для . Выберите два правильных ответа.

        1. Атрибут id должен быть определен для .
        2. Атрибут области должен быть определен для .
        3. Атрибут class должен быть определен для .
        4. Должен включать либо тип, либо атрибут класса, либо и то, и другое.
        <р>16. Какие из них являются законными атрибутами директивы страницы. Выберите два правильных ответа.

        <р>17. Что из следующего представляет XML-эквивалент этого оператора. Выберите одно верное утверждение

        1. Директива include не имеет XML-эквивалента.
        <р>18. Предположим, вам нужно написать JSP-страницу, которая складывает числа от одного до десяти, а затем распечатать результат.


        // XXX — Добавить j к сумме

        // YYY — Отобразить эту сумму

        Какое выражение при размещении в позиции XXX можно использовать для вычисления суммы. Выберите одно верное утверждение

        <р>19. Теперь рассмотрим тот же пример JSP, что и в предыдущем вопросе. Что нужно добавить в позицию YYY, чтобы вывести сумму десяти чисел. Выберите одно верное утверждение

        <р>20. Страницы JSP имеют доступ к неявным объектам, которые отображаются автоматически. Одним из таких доступных объектов является request. Объект запроса является экземпляром какого класса?

        22. Java-бин со свойством color загружается с помощью следующего оператора

          1. Выберите один правильный ответ.
            1. Создается ошибка, поскольку атрибут значения setAttribute не определен.
            2. Атрибуту цвета присваивается нулевое значение.
            3. Атрибуту цвета присваивается значение «».
            4. Если есть ненулевой параметр запроса с названием color, то его значение присваивается свойству color плода Java Bean.

            23. Директива page используется для передачи информации о странице в JSP-контейнер. Какие из них являются допустимым синтаксисом директивы страницы. Выберите два правильных утверждения

            24. Является ли следующий код JSP законным? Выберите одно верное утверждение.

            1. Да. Это допустимый синтаксис JSP.
            2. Нет. Этот код вызовет синтаксические ошибки.

            25. Страница JSP должна генерировать файл XML. Какой атрибут директивы страницы можно использовать, чтобы указать, что страница JSP создает файл XML.

            1. Тип контента
            2. сгенерироватьXML
            3. тип
            4. выходнойXML

            26. Страница JSP использует класс java.util.ArrayList много раз. Вместо того, чтобы каждый раз обращаться к классу по полному имени пакета, мы хотим просто использовать ArrayList. Какой атрибут директивы страницы должен быть указан для достижения этого. Выберите один правильный ответ.

            1. расширяется
            2. импорт
            3. включить
            4. пакет
            5. путь к классам

            27. Какие из них верны.Выберите два правильных ответа.

            1. Значением по умолчанию атрибута isThreadSafe директивы страницы является true.
            2. Если для атрибута isThreadSafe директивы страницы установлено значение true, то контейнер JSP последовательно отправляет запрос на страницу.
            3. Если для атрибута isThreadSafe директивы страницы задано значение true, поток создается для каждого запроса страницы.
            4. Установка для атрибута isThreadSage значения true для страниц JSP может привести к снижению производительности.

            28. Что из следующего является примером директивы JSP. Выберите два правильных ответа.

            1. включить
            2. исключить
            3. импорт
            4. библиотека тегов
            5. сервлет
            6. страница

            29. Что из этого верно в отношении директивы include. Выберите один правильный ответ.

            1. Включаемый файл должен иметь расширение jspf.
            2. Синтаксис XML директивы include в .
            3. Содержимое файла, включенного с помощью директивы include, не может ссылаться на локальные переменные исходной страницы.
            4. При использовании директивы include контейнер JSP обрабатывает включаемый файл так, как если бы он был частью исходного файла.
            <р>30. Назовите неявную переменную, доступную для страниц JSP, которую можно использовать для доступа ко всем другим неявным объектам.

            Чтобы просмотреть информацию о файле или папке, щелкните его правой кнопкой мыши и выберите "Свойства" . Вы также можете выбрать файл и нажать Alt + Enter .

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

            Информация, представленная на вкладке "Основные", поясняется ниже. Также есть вкладки «Разрешения» и «Открыть с помощью». Для определенных типов файлов, таких как изображения и видео, будет дополнительная вкладка с такой информацией, как размеры, продолжительность и кодек.

            Основные свойства

            Вы можете переименовать файл, изменив это поле. Вы также можете переименовать файл вне окна свойств. См. раздел Переименование файла или папки .

            Это поможет определить тип файла, например документ PDF, текст OpenDocument или изображение JPEG. Тип файла определяет, среди прочего, какие приложения могут открывать файл. Например, вы не можете открыть картинку с помощью музыкального проигрывателя. Дополнительные сведения об этом см. в разделе Открытие файлов в других приложениях.

            Тип файла MIME указан в скобках; Тип MIME — это стандартный способ, которым компьютеры обозначают тип файла.

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

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

            Размеры могут быть указаны в байтах, КБ, МБ или ГБ; в случае трех последних размер в байтах также будет указан в скобках. Технически 1 КБ – это 1024 байта, 1 МБ – 1024 КБ и т. д.

            Расположение каждого файла на вашем компьютере определяется его абсолютным путем. Это уникальный «адрес» файла на вашем компьютере, состоящий из списка папок, в которые вам нужно будет зайти, чтобы найти файл. Например, если у Джима есть файл с именем Resume.pdf в его домашней папке, его родительская папка будет /home/jim, а его местоположение будет /home/jim/Resume.pdf .

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

            Эмиль Дркусик

            Предложение SELECT, вероятно, является самой важной командой SQL. Он используется для возврата результатов из нашей базы данных (баз данных), и как бы просто это ни звучало, на самом деле это может быть очень сложно. В этой статье мы познакомим вас с оператором SELECT, а в следующих статьях мы расскажем о более сложных вещах.

            Мотивация

            В этой серии у нас было 4 статьи, в которых мы создали простую базу данных, заполнили ее некоторыми данными и объяснили, что такое первичные и внешние ключи. Вот предварительные условия, необходимые для того, чтобы начать «играть» с нашими данными:

            Модель данных SQL

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

            • Анализ данных, скорее всего, с помощью операторов SELECT
            • Отслеживание производительности системы
            • Внесите изменения в модель данных для поддержки новых функций.

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

            Инструкция SELECT — Синтаксис

            Все команды SQL важны и необходимы, особенно эти 4 наиболее часто используемые — SELECT, INSERT, UPDATE, DELETE. Поэтому утверждение, что оператор SELECT является самым важным, неверно. Это так же важно, как и другие, но оно определенно используется чаще всего. Умение написать SELECT, чтобы получить именно то, что вы хотели, является очень желательным знанием в наши дни. Помимо написания оператора, возвращающего правильный результат, вы почти всегда должны (если вы пишете одноразовый запрос, и он занимает 2 секунды вместо 0,1 секунды, с этим можно смириться) всегда следить за тем, чтобы запрос написан оптимальным образом.

            Читайте также: