T-SQL

Büyük boyutlu varchar kolonların join’lerde performansının geliştirilmesi

Geçenlerde sql server sorgularımın performansını geliştirmek için yaptığım araştırmalarda bulduğum bir trick :

Veri tabanımda bulunan bir tabloda bazı verileri içeren pageData adında nvarchar(3000) tipinde bir kolonum var. Başka bir veri tabanındaki benzer tablo ile pageData kolonunu periyodik olarak join’leyerek bazı işlemler gerçekleştiriyorum. Ancak pageData kolonumun veri tipi nvarchar(3000) olduğu için index tanımlayamıyorum bu yüzden sorgum aşırı derecede yavaş çalışıyor.

Index tanımlama için boyut sınıfı

(daha&helliip;)

SQL İpuçları

Bir tablodaki bir kolonun satırlarını tek bir text haline getirmek için aşağıdaki script ihtiyacımızı karşılayacaktır.

FirstName
Gustavo
Catherine
Kim

Örneğin Contact tablosunda bulunan FirstName kolonundaki bilgileri script çalıştırıldığında “Gustavo, Catherine, Kim” şeklinde görüntülenecektir.

DECLARE @Names VARCHAR(8000)
SELECT @Names = COALESCE(@Names + ', ', '') + ISNULL(FirstName, 'N/A') FROM Person.Contact

-- Veya

SELECT Stuff(
  (SELECT N', ' + FirstName FROM Person.Contact FOR XML PATH(''),TYPE) .value('text()[1]','nvarchar(max)'),1,2,N'')

Yukarıdaki işlemin tersini yapma ihtiyacı olduğunda ise aşağıdaki fonksiyon ile tekrar text halinden tablo haline dönüşüm gerçekleştirebilirsiniz.

--Kullanım
SELECT * FROM dbo.Split('Gustavo, Catherine,Kim',',')

--Script
CREATE FUNCTION [dbo].[Split](@STRING varchar(MAX), @Delimiter char(1))
RETURNS @Results TABLE (indx int, Items varchar(MAX))
AS

    BEGIN
    DECLARE @INDEX INT;DECLARE @SLICE varchar(MAX);
    SELECT @INDEX = 1;
    IF @STRING IS NULL RETURN
    DECLARE @i as int ;
    SET @i = 1;
    WHILE @INDEX !=0
        BEGIN
        	SELECT @INDEX = CHARINDEX(@Delimiter,@STRING)
        	IF @INDEX !=0
        		SELECT @SLICE = LEFT(@STRING,@INDEX - 1)
        	ELSE
        		SELECT @SLICE = @STRING
        	INSERT INTO @Results(indx, Items) VALUES(@i, @SLICE)
        	SELECT @STRING = RIGHT(@STRING,LEN(@STRING) - @INDEX)
        	IF LEN(@STRING) = 0 BREAK
            SET @i = @i + 1
        END
    RETURN
END
00002254465 gibi kayıtların başındaki sıfırları silebilmek için kullanılabilecek bir fonksiyon;
CREATE FUNCTION RemoveLeadingZerosFromVarChar
(
      @inputStr varchar(max)
)
RETURNS varchar(max)
AS
BEGIN
      DECLARE @Result varchar(max)
 
      SELECT @Result = replace(replace(ltrim(replace(
          replace(ltrim(@inputStr), ' ', '¬') 
          , '0', ' ') 
          ) 
          , ' ', '0') 
          , '¬', ' ') 
      RETURN @Result
END
GO
İki tarih arasındaki çalışma günlerini bulmak için kullanılabilecek script
CREATE FUNCTION dbo.GetWorkingDays
  ( @StartDate datetime,
    @EndDate datetime )
RETURNS INT
AS
BEGIN
  DECLARE @WorkDays int, @FirstPart int
  DECLARE @FirstNum int, @TotalDays int
  DECLARE @LastNum int, @LastPart int
  IF (DATEDIFF(day, @StartDate, @EndDate) < 2)
    BEGIN
      RETURN ( 0 )
    END
  SELECT
   @TotalDays = DATEDIFF(day, @StartDate, @EndDate) - 1,
   @FirstPart = CASE DATENAME(weekday, @StartDate)
                 WHEN 'Sunday' THEN 6
                 WHEN 'Monday' THEN 5
                 WHEN 'Tuesday' THEN 4
                 WHEN 'Wednesday' THEN 3
                 WHEN 'Thursday' THEN 2
                 WHEN 'Friday' THEN 1
                 WHEN 'Saturday' THEN 0
               END,
   @FirstNum = CASE DATENAME(weekday, @StartDate)
                 WHEN 'Sunday' THEN 5
                 WHEN 'Monday' THEN 4
                 WHEN 'Tuesday' THEN 3
                 WHEN 'Wednesday' THEN 2
                 WHEN 'Thursday' THEN 1
                 WHEN 'Friday' THEN 0
                 WHEN 'Saturday' THEN 0
               END
  IF (@TotalDays < @FirstPart)
     BEGIN
       SELECT @WorkDays = @TotalDays
     END
  ELSE
     BEGIN
       SELECT @WorkDays = (@TotalDays - @FirstPart) / 7
       SELECT @LastPart = (@TotalDays - @FirstPart) % 7
       SELECT @LastNum = CASE
         WHEN (@LastPart < 7) AND (@LastPart > 0) THEN @LastPart - 1
         ELSE 0
       END
       SELECT @WorkDays = @WorkDays * 5 + @FirstNum + @LastNum
     END
  RETURN ( @WorkDays )
END
GO

Kullanımı ;

SELECT dbo.GetWorkingDays ('2012-01-01', '2012-12-01')