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

Производительность SQL-сервера на большом расстоянии

Разумно ли ожидать достойной производительности от SQL-сервера, подключенного через оптоволоконную частную WAN - на расстоянии 5000 км. Оператор связи говорит нам, что эта сеть является «лучшей» из возможных и обеспечит гарантированную задержку менее 50 мс.

Наша база данных в настоящее время подключена через гигабитный Ethernet к другим нашим машинам в том же центре обработки данных. Нам нравится наличие «удлинения LAN» на 5000 км между двумя DC. Но когда мы подключаемся через Интернет и VPN, мы обнаруживаем, что производительность очень низкая при выполнении больших объемов небольших транзакций. У нас нет опыта работы с WAN, поэтому мы не уверены, что большинство компаний делают в таких случаях. Можем ли мы смоделировать «задержку» в 5000 км / с?

При скорости 5000 км / с задержка составит ~ 17 мс. Вниз по оптическому волокну, больше похоже на 25 мс. И это лучший вариант межсерверного волокна без задержек для преобразования мультимедиа, коммутации, маршрутизации, ответа сервера и т. Д.

Минимум 25 мс, гарантированный максимум 50 мс ...

да, есть инструменты для имитации медленного соединения, например

http://jagt.github.io/clumsy/ - программа для Windows для изменения сетевого трафика

http://wanem.sourceforge.net/ - Linux LiveCD для эмуляции WAN

и много предложений https://stackoverflow.com/questions/130354/how-do-i-simulate-a-low-bandwidth-high-latency-environment и https://stackoverflow.com/questions/1094760/network-tools-that-simulate-slow-network-connection

Сравните опросы sys.dm_os_wait_stats между периодом имитации высокой сетевой задержки и идентичным периодом нормальной сетевой задержки (для той же клиентской нагрузки и той же статистики базы данных). Например, следующий сценарий может использоваться для сравнения [wait_rate (ms / sec)] для 'ASYNC_NETWORK_IO' [wait_type]. Различия, измеренные от X до низких XX%, скорее всего, вызваны влиянием фонового шума (т.е. они бессмысленны). Различия, измеряемые в XXX%, вероятно, будут актуальными. Чтобы дать вам качественное представление об относительной важности wait_rates, вы увидите: если ваш SQL Server должен иметь 500 активных рабочих потоков, и если все 500 из этих потоков ожидают только одного wait_type (в течение некоторого заданного периода времени) , тогда [wait_rate (ms / sec)] для этого [wait_type] будет 500 000 мс / сек. Обычно я игнорирую [wait_rate (ms / sec)], которые меньше 1000 ms / sec.

Следующий сценарий был написан для сбора данных за период в 20 секунд. Это можно изменить (в соответствии с вашими требованиями к тестированию). Сценарий не объединяет типы ожидания по категориям (например, этот сценарий не объединяет все ожидания PAGEIO% вместе).

DECLARE @hhmmssDelay CHAR(8) = '00:00:20'

SET NOCOUNT ON

CREATE TABLE 
    #ignored
    (
    wait_type NVARCHAR(60) PRIMARY KEY
    )
INSERT
    #ignored
SELECT 'BAD_PAGE_PROCESS'
UNION SELECT 'BROKER_EVENTHANDLER'
UNION SELECT 'BROKER_RECEIVE_WAITFOR'
UNION SELECT 'BROKER_TASK_STOP'
UNION SELECT 'BROKER_TO_FLUSH'
UNION SELECT 'BROKER_TRANSMITTER'
UNION SELECT 'CHECKPOINT_QUEUE'
UNION SELECT 'CLR_AUTO_EVENT'
UNION SELECT 'CLR_MANUAL_EVENT'
UNION SELECT 'DBMIRROR_EVENTS_QUEUE'
UNION SELECT 'DISPATCHER_QUEUE_SEMAPHORE'
UNION SELECT 'FT_IFTS_SCHEDULER_IDLE_WAIT'
UNION SELECT 'FT_IFTSHC_MUTEX'
UNION SELECT 'KSOURCE_WAKEUP'
UNION SELECT 'LAZYWRITER_SLEEP'
UNION SELECT 'LOGMGR_QUEUE'
UNION SELECT 'ONDEMAND_TASK_QUEUE'
UNION SELECT 'PREEMPTIVE_OS_AUTHENTICATIONOPS'
UNION SELECT 'PREEMPTIVE_OS_GETPROCADDRESS'
UNION SELECT 'REQUEST_FOR_DEADLOCK_SEARCH'
UNION SELECT 'RESOURCE_QUEUE'
UNION SELECT 'SLEEP_BPOOL_FLUSH'
UNION SELECT 'SLEEP_SYSTEMTASK'
UNION SELECT 'SLEEP_TASK' 
UNION SELECT 'SQLTRACE_BUFFER_FLUSH'
UNION SELECT 'WAITFOR'
UNION SELECT 'XE_DISPATCHER_JOIN'
UNION SELECT 'XE_DISPATCHER_WAIT'
UNION SELECT 'XE_TIMER_EVENT'
UNION SELECT 'SQLTRACE_INCREMENTAL_FLUSH_SLEEP'
UNION SELECT 'DIRTY_PAGE_POLL'
UNION SELECT 'HADR_FILESTREAM_IOMGR_IOCOMPLETION'  -- May be useful for  AlwaysON (AKA Hadron)

SELECT 
    GETDATE() 'Poll'
    , ows.*
INTO 
    #os_wait_stats  
FROM 
    sys.dm_os_wait_stats ows
LEFT JOIN
    #ignored i
ON
    i.wait_type = ows.wait_type
WHERE
    i.wait_type IS NULL


WAITFOR DELAY @hhmmssDelay

INSERT
    #os_wait_stats 
SELECT 
    GETDATE() 'Poll', ows.*
FROM 
    sys.dm_os_wait_stats ows
LEFT JOIN
    #ignored i
ON
    i.wait_type = ows.wait_type
WHERE
    i.wait_type IS NULL

DECLARE @SecondsBetweenPolls INT
SELECT 
    @SecondsBetweenPolls=DATEDIFF(SECOND,MIN(Poll),MAX(Poll))
FROM
    #os_wait_stats

DECLARE @SecondsSinceSQLServerStarted BIGINT
DECLARE @LastPoll DATETIME
SELECT 
    @LastPoll=MAX(Poll)
FROM
    #os_wait_stats

SELECT 
    @SecondsSinceSQLServerStarted =DATEDIFF(SECOND, sqlserver_start_time, @LastPoll)
FROM sys.dm_os_sys_info


SELECT
    CONVERT(NUMERIC(38,0),(Later.wait_time_ms-Earlier.wait_time_ms))/CONVERT(NUMERIC(38,0),@SecondsBetweenPolls) 'wait_rate (ms/Sec)'
    ,Later.wait_type
    ,Later.waiting_tasks_count-Earlier.waiting_tasks_count 'waiting_tasks_count'
    ,Later.signal_wait_time_ms-Earlier.signal_wait_time_ms 'signal_wait_time_ms' 
    ,Later.wait_time_ms-Earlier.wait_time_ms 'wait_time_ms'
    ,CONVERT(NUMERIC(38,0),(Later.wait_time_ms))/CONVERT(NUMERIC(38,0),@SecondsSinceSQLServerStarted)'cumulative_wait_rate (ms/Sec)'
    ,Later.wait_time_ms 'cumulative_wait_time_ms'
    ,Earlier.Poll 'earlier_poll'
    ,Later.Poll 'later_poll'
    ,Earlier.max_wait_time_ms 'earlier_max_wait_time_ms'
    ,Later.max_wait_time_ms 'later_max_wait_time_ms'

    FROM    
    #os_wait_stats Later
JOIN
    (
    SELECT
        wait_type
        ,wait_time_ms
        ,waiting_tasks_count
        ,signal_wait_time_ms
        ,max_wait_time_ms
        ,Poll
    FROM
        #os_wait_stats
    WHERE
        Poll = 
            (
            SELECT 
                MIN(Poll) 
            FROM 
                #os_wait_stats
            )
    ) as Earlier
ON
    Earlier.wait_type = Later.wait_type
WHERE
    Later.wait_time_ms-Earlier.wait_time_ms > 0
ORDER BY
    CONVERT(NUMERIC(38,0),(Later.wait_time_ms-Earlier.wait_time_ms))/CONVERT(NUMERIC(38,0),@SecondsBetweenPolls) -- 'wait_rate (ms/Sec)'
DESC

GO
DROP TABLE #os_wait_stats
GO
DROP TABLE #ignored