Средняя скорость вставки - PullRequest
3 голосов
/ 23 января 2012

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

  • Пиковые вставки в минуту
  • Пиковые вставки в секунду
  • Среднее количество вставок в минуту
  • Среднее количество вставок в секунду

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

Есть ли более элегантное решение T-SQL для этой проблемы?

Ответы [ 3 ]

4 голосов
/ 24 января 2012

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

-- if you weren't grouping by minutes and seconds this would
-- probably look more 'elegant'
SELECT      
    GROUPING_ID(
        YEAR(orderdate), 
        MONTH(orderdate), 
        DAY(orderdate), 
        DATEPART(hour, orderdate),
        DATEPART(MINUTE, orderdate),
        DATEPART(SECOND, orderdate)) AS grp_id,
    MAX([Insertions])                AS max_insertions,
    AVG([Average])                   AS avg_insertions,
    YEAR(orderdate)                  AS order_year,
    MONTH(orderdate)                 AS order_month, 
    DAY(orderdate)                   AS order_day, 
    DATEPART(HOUR, orderdate)        AS order_hour,
    DATEPART(MINUTE, orderdate)      AS order_minute,
    DATEPART(SECOND, orderdate)      AS order_second -- this will be null if the grouping set is minute
FROM Sales.Orders
GROUP BY
   GROUPING SETS
   (
       (
            -- grouping set 1: order second
            YEAR(orderdate), 
            MONTH(orderdate), 
            DAY(orderdate), 
            DATEPART(hour, orderdate),
            DATEPART(MINUTE, orderdate),
            DATEPART(SECOND, orderdate)
        ),
        (
            -- grouping set 2: order minute
            YEAR(orderdate), 
            MONTH(orderdate), 
            DAY(orderdate), 
            DATEPART(hour, orderdate),
            DATEPART(MINUTE, orderdate)
        )
    );
2 голосов
/ 24 января 2012

В продолжение ответа J Coopers, я думаю, что функция Rollup может быть то, что вы ищете.

SELECT      
    MAX([Insertions])                AS max_insertions,
    AVG([Average])                   AS avg_insertions,
     YEAR(orderdate),    AS YEAR
    MONTH(orderdate),   AS MONTH
    DAY(orderdate), AS DAY
    DATEPART(hour, orderdate), AS HOUR
    DATEPART(MINUTE, orderdate), AS MINUTE
    DATEPART(SECOND, orderdate) AS SECOND

FROM Sales.Orders
GROUP BY ROLLUP(
        YEAR(orderdate), 
        MONTH(orderdate), 
        DAY(orderdate), 
        DATEPART(hour, orderdate),
        DATEPART(MINUTE, orderdate),
        DATEPART(SECOND, orderdate)
    )   
2 голосов
/ 23 января 2012

GROUP BY - это путь.

Я бы просто сделал CTE для каждого временного интервала, который вам нужен, и выбрал бы максимум для каждого:

;WITH CTEMinute AS
(
    SELECT  YEAR(datefield) yr, 
            MONTH(datefield) mo, 
            DAY(datefield) d, 
            DATEPART(hour, datefield) hr, 
            DATEPART(minute, datefield) Mint, 
            COUNT(*) as 'Inserts'
    FROM MyTable
    GROUP BY    YEAR(datefield), 
                MONTH(datefield), 
                DAY(datefield), 
                DATEPART(hour, datefield), 
                DATEPART(minute, datefield)
)
,CTESecond AS
(
    SELECT YEAR(datefield) yr, 
            MONTH(datefield) mo, 
            DAY(datefield) d, 
            DATEPART(hour, datefield) hr, 
            DATEPART(minute, datefield) Mint, 
            DATEPART(second, datefield) sec, 
            COUNT(*) as 'Inserts'
    FROM MyTable
    GROUP BY    YEAR(datefield), 
                MONTH(datefield), 
                DAY(datefield), 
                DATEPART(hour, datefield), 
                DATEPART(minute, datefield), 
                DATEPART(second, datefield)

)

Затем вы можете просто выбрать из этих CTE s, чтобы получить значения max / min / avg за единицу времени.

Если вы хотите, чтобы он был более элегантным, вы потенциально можете просто сделать на CTE столько тонкости, сколько вы, вероятно, захотите (то есть, миллисекунды или что-то еще), и тогда вы можете SELECT / GROUP BY это.

Проблема с этим заключается в том, что CTE не очень хорошо работают, так как они в основном одноразовые представления без индексов или чего-либо еще, поэтому объединение CTE в другом запросе быстро приведет к неудаче.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...