Sorgunun bir kısmı CPU'yu uzun süre maksimize etmek, GROUP BY deyimindeki işlevler ve gruplamanın her zaman bu örnekte benzersiz bir sıralama gerektireceği gerçeğidir. Zaman damgası alanındaki bir dizin başlangıç filtresine yardımcı olurken, bu işlem filtrenin eşleştiği her satırda gerçekleştirilmelidir. Bunu hızlandırmak, Alex'in önerdiği aynı işi yapmak için daha verimli bir yol kullanıyor, ancak yine de büyük bir verimsizliğiniz var, çünkü sorgu planlayıcıyı kullandığınız işlev birleşimi bulamayacak herhangi bir indeks tarafından yardımcı olacak bir şey, bu yüzden önce gruplama değerlerini hesaplamak için fonksiyonları çalıştıran her satırdan geçmesi gerekir, ancak daha sonra verileri sipariş edebilir ve sonuçta ortaya çıkan gruplamalar üzerinden toplamaları hesaplayabilir.
Dolayısıyla çözüm, bir şekilde süreç grubunu bir dizin için kullanabileceği bir şey haline getirmek veya tüm eşleşen satırları aynı anda dikkate alma ihtiyacını ortadan kaldırmaktır.
Saate yuvarlanan süreyi içeren her satır için fazladan bir sütun tutabilir ve bu sütunu bu tür sorgularda kullanmak üzere dizine ekleyebilirsiniz. Bu, verilerinizi denormalize eder, bu nedenle "kirli" hissedebilir, ancak işe yarar ve gelecekteki kullanım için tüm toplamaları önbelleğe almaktan (ve temel veriler değiştikçe bu önbelleği güncellemekten) daha temiz olur. Ek sütun, başka bir yerde mantık tarafından korunmak yerine tetikleyici ile korunmalı veya kalıcı bir hesaplanmış sütun olmalıdır, çünkü bu, veri ekleyebilecek veya zaman damgası sütunlarını veya mevcut satırları güncelleyebilecek tüm mevcut ve gelecekteki yerleri yeni sütunu. Yine de MIN (zaman damgası) çıktısını alabilirsiniz. Sorgunun bu şekilde sonuçlanacağı şey hala tüm satırların aşağı doğru bir yürüyüşüdür (bu önlenemez, açıkçası) ama dizin sırasını yapabilir, gruplama / toplama gerçekleştirilmeden önce dizine eklenmemiş bir sıralama işlemi için tüm satır kümesini hatırlamak yerine, her gruplama için bir satırın dizinde bir sonraki değere ulaşması. Şu anda bakmakta olanı veya geri kalanını işlemek için önceki gruplama değerlerinden herhangi bir satırı hatırlaması gerekmeyeceğinden çok daha az bellek kullanacaktır.
Bu yöntem, tüm sonuç kümesi için bellekte bir yer bulma ihtiyacını ortadan kaldırır ve grup işlemi için dizinsiz sıralamayı yapar ve grup değerlerinin hesaplamasını büyük sorgudan kaldırır (bu işi, veriler) içerir ve bu tür sorguların, toplanan sonuçların ayrı bir deposunu tutmaya gerek kalmadan kabul edilebilir şekilde çalışmasına izin vermelidir.
Bir yöntem değildirverilerinizi denormalize edin, ancak yine de fazladan bir yapı gerektiriyorsa, bir "zaman tablosu" kullanmaktır. Bu tablo, DB veya kayda değer bir boyutta önemli miktarda alan tüketmez - 100 yıllık bir zaman aralığını iki tarihin bir satırını içeren bir tabloyu kapsamak için (saatin başlangıcı ve bitişi, örneğin '2011-01-01 @ 00: 00: 00.0000 ',' 2011-01-01 @ 00: 00: 59.9997 ', "9997", bir DATETIME alanının sonraki saniyeye yuvarlanmayacak en az milisaniye sayısıdır. kümelenmiş birincil anahtar ~ 14Mbyte yer kaplar (satır başına 8 + 8 bayt * 24 saat / gün * 365,25 gün / yıl * 100, ayrıca kümelenmiş dizinin ağaç yapısının ek yükü için biraz, ancak bu ek yük önemli olmayacaktır) .
SELECT CONVERT(VARCHAR, [timestamp], 1)+' '+ CAST(DATEPART(Hh,[timestamp]) as VARCHAR) AS TimeStampHour
, MIN([timestamp]) as TimeStamp
, AVG(MyField) As AvgField
FROM TimeRangeByHours tt
INNER JOIN MyData md ON md.TimeStamp BETWEEN tt.StartTime AND tt.EndTime
WHERE tt.StartTime > '4/10/2011'
GROUP BY tt.StartTime
ORDER BY tt.StartTime
Bu, sorgu planlayıcının MyData.TimeStamp üzerindeki dizini kullanılacak şekilde ayarlayabileceği anlamına gelir. Sorgu planlayıcısı, MyData.TimeStamp dizininde adım adım uysal tablodan aşağı doğru yürüyebileceği kadar parlak olmalı, yine gruplama başına bir satır çıktısı almalı ve her grup veya satırı bir sonraki gruplama değerine ulaştıkça atacaktır. Aradaki tüm satırları RAM'de bir yerde saklamak ve üzerinde benzersiz bir sıralama yapmak yok. Elbette bu yöntem, zaman tablosunu oluşturmanızı ve hem geriye hem de ileriye doğru yeterince genişlediğinden emin olmanızı gerektirir, ancak "ekstra sütun" seçeneğinin gerektireceği gibi farklı sorgulardaki birçok tarih alanına karşı sorgular için zaman tablosunu kullanabilirsiniz. bu şekilde filtrelemek / gruplamak için ihtiyaç duyduğunuz her tarih alanı için fazladan hesaplanmış bir sütun ve tablonun küçük boyutu (10'a yayılması gerekmedikçe,
Zaman tablosu yöntemi, mevcut durumunuza ve hesaplanan sütun çözümüne kıyasla (bu oldukça avantajlı olabilir) ekstra bir farka sahiptir: yalnızca yukarıdaki örnek sorgudaki INNER JOIN'i değiştirerek veri olmayan dönemler için satırları döndürebilir SOL DIŞ biri olmak.
Bazı insanlar fiziksel bir zaman çizelgesine sahip olmayıp, her zaman bir tablo döndürme işlevinden döndürmeyi önerir. Bu, zaman tablosunun içeriğinin hiçbir zaman diskte depolanmadığı (veya okunması gerektiği) anlamına gelir ve işlev iyi yazılmışsa, zaman çizelgesinin ne kadar zaman içinde ileri ve geri yayılması gerektiği konusunda endişelenmeniz gerekmez, ancak ben şüphe bazı satırlar için bir bellek içi tablo üretme CPU maliyeti her sorgu fiziksel zaman tablosunu oluşturma (ve süresinin ilk sürümünün sınırının ötesine uzanması gerekiyorsa sürdürme) küçük bir tasarruf değerinde değer.
Yan not: Orijinal sorgunuzda da DISTINCT yantümcesine ihtiyacınız yoktur. Gruplama, bu sorguların dikkate alınan periyot başına yalnızca bir satır döndürmesini sağlar; yok sayın ve fazladan CPU zamanı kullanmayın).