Назад | Перейти на главную страницу

Как SQL Server обрабатывает одновременные запросы на чтение / запись?

Задний план:

У нас есть приложение, которое активно использует базу данных SQL Server 2008. Мы пытаемся оптимизировать это приложение. Он был однопоточным, и мы заметили при ведении журнала / профилировании приложения, что самым большим узким местом были операции чтения / записи db. Некоторые звонки занимали до 100 мсек, что для нас слишком долго. Среди других оптимизаций мы выделили некоторые из этих вызовов в отдельный поток. Только благодаря этому изменению мы наблюдаем значительное улучшение времени обработки (код почти такой же, только некоторые были перемещены в другой поток)

Вопрос:

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

Мне интересно, как SQL Server обрабатывает два одновременных запроса (любую комбинацию чтения / записи) из разных потоков. Может ли он как-то выполнять их одновременно?

Таким образом, я бы предположил, что общее время запросов Query1 + Query2, вызываемых один за другим, будет аналогично одновременному вызову Query1 + Query2.

Это работает на двухъядерном сервере.

SQL Server - это многопользовательская база данных. В первую очередь он предназначен для обработки нескольких одновременных запросов.

В идеале два запроса, которые принимают A + B при последовательном выполнении, будут принимать MAX (A, B) при одновременном выполнении.

Чтобы предотвратить чтение или запись поврежденных данных, SQL Server использует Сделки и Блокировка. В дополнение к этому, приложения также могут управлять параллелизмом (оптимистичный, например).

Я думаю, что Дэвид Б. дал хороший ответ, но я просто собираюсь немного расширить его на примере.

Допустим, у вас есть две таблицы в вашей базе данных, Table_A и Table_B. Сервер имеет несколько процессоров. Кроме того, дисковая подсистема помещает каждую таблицу на отдельный диск / LUN / шпиндель (какова бы ни была правильная терминология, я не большой специалист по оборудованию). Кроме того, на сервере есть несколько сетевых карт.

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

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

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

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

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