Home > SQL-Server 2005 > Datensatzlänge einer Abfrage schätzen

Datensatzlänge einer Abfrage schätzen

Gerade wenn man ein bestehendes Datenbanksystem optimieren möchte, könnte die Frage nach der durchschnittlichen Breite einer Abfrage auftauchen. Speziell wenn man keine Tabelle zur Hand hat die in ihren Properties zumindest den verbrauchten Speicherplatz anzeigt, ist die nachfolgende Prozedur vielleicht ganz nützlich.

Es werden für eine gegebene Abfrage die Ergebnisse in eine temporäre Tabelle geschrieben und dann mittels der Funktion DATALENGTH die tatsächliche Länge eines Feldes bestimmt. Die durchschnittliche Summe der Gesamtlänge eines Datensatzes wird in der Rückgabe angezeigt.

Wenn man diese Durchschnittslänge mit der Anzahl der Datensätze multipliziert, erhält man den Nettowert des Datenvolumens das transferiert wird. (zumindest annähernd;))

Wenn ein Feld einen NULL-Wert enthält, setzt die Prozedur eine Feldlänge von 4 Byte ein. Dies wird als Mittelwert einer leeren Feldlänge verwendet und könnte in einer weiteren Ausbaustufe ggf. noch aus den System-Views für die Feldtypen genauer bestimmt werden.


Die Abfrage sollte eine repräsentative Menge an Daten zurückliefern. Es ist vor allem bei sehr großen Ergebnismengen ein wenig Vorsicht angesagt, um nicht die Temp-Datenbank in Bedrängnis geraten zu lassen ;)

 T-SQL |  copy code |? 
01
CREATE PROCEDURE dbo.GetAvgRecordWidth
02
  @Datenbank sysname
03
, @SourceCmd NVARCHAR(MAX)
04
AS
05
BEGIN
06
    DECLARE @TempName NVARCHAR(1000)
07
    DECLARE @IntoTemp NVARCHAR(1000)
08
 
09
    SET @TempName = '##TempCntSource_' + REPLACE(newid(),'-','')
10
 
11
    SET @IntoTemp = ' into ' + @TempName + ' FROM '
12
 
13
    SET @SourceCmd = STUFF(@SourceCmd,CHARINDEX('from',LOWER(@SourceCmd)),4,@IntoTemp)
14
 
15
    -- ---------------------------------------------------------------------------
16
    DECLARE @Cmd NVARCHAR(MAX)
17
 
18
    SET @Cmd = 'USE ' + @Datenbank + '; ' + @SourceCmd + N'
19
    declare  @SQL nvarchar(max)
20
            ,@Feld sysname
21
            ,@Delim varchar(100)
22
 
23
    set @Delim = N''Select avg(''
24
 
25
    set @SQL   = N''''
26
 
27
    declare Colcur cursor for
28
    select c.name
29
    from tempdb.sys.objects o
30
        join tempdb.sys.columns c on c.object_id = o.object_id
31
    where o.name like ''<##TempCntSource>%''
32
 
33
    open Colcur
34
 
35
    fetch next from  Colcur into @Feld
36
 
37
    while @@fetch_status = 0
38
    begin
39
        set @SQL = @SQL + @Delim + ''isnull(DATALENGTH('' + @Feld + ''),4)''
40
        set @Delim = ''+''
41
 
42
        fetch next from  Colcur into @Feld
43
    end
44
 
45
    close Colcur
46
    deallocate Colcur
47
 
48
    set  @SQL = @SQL + '') from <##TempCntSource>''
49
 
50
    exec sp_executesql @SQL
51
 
52
    drop table <##TempCntSource>
53
    '
54
 
55
    SET @Cmd = REPLACE(@Cmd,'<##TempCntSource>',@TempName)
56
 
57
    EXEC SP_EXECUTESQL @Cmd
58
END

Der Aufruf sieht dann wie folgt aus:

 T-SQL |  copy code |? 
1
DECLARE @Stmt NVARCHAR(MAX)
2
DECLARE @Datenbank sysname
3
 
4
SET @Datenbank = N'AdventureWorks'
5
SET @Stmt      = N'select * from HumanResources.Employee'
6
 
7
EXEC dbo.GetAvgRecordWidth @Datenbank,@Stmt

have fun ;-)

KategorienSQL-Server 2005
  1. Bisher keine Kommentare
  1. Bisher keine Trackbacks