SQL что быстрее осталось 2 или конвертировать (varchar (2), 'Chgffgjjx') - PullRequest
2 голосов
/ 10 февраля 2010

Если я хочу вернуть первые два символа строки, какой метод самый лучший / самый быстрый?

Также, если у меня есть дата и я хочу группировать по дням, я буду использовать convert(varchar(10),getdate()) так как наш формат БД в формате гггг / мм / дд, который дал бы «2010/02/10», если бы я хотел группировать по месяцам, я бы использовал varchar(7) вместо «2010/02»

Есть ли более быстрый способ достичь того же?

Ответы [ 6 ]

3 голосов
/ 10 февраля 2010

Нет никакой разницы в производительности между этими двумя. Однако - и это не совсем ясно из вашего вопроса - если вы переводите это в состояние WHERE в отличие от вывода столбца в вашем запросе, оба они очень и очень плохие.

Строковые функции, такие как LEFT, SUBSTRING и CONVERT (при использовании для приведения), не могут быть обработаны, что означает, что обычно эффективный поиск индекса будет превращен в дорогостоящее полное сканирование индекса. Если вы хотите запросить первые два символа поля, вы должны написать запрос следующим образом:

SELECT Col1, Col2, ...
FROM Table
WHERE StringCol LIKE 'AB%'

Опять же, это относится только к фильтрам; если LEFT / SUBSTRING находится в выводе столбца (т.е. SELECT LEFT(Col1, 2)), то вам не нужно беспокоиться о производительности.

1 голос
/ 10 февраля 2010

Что касается вашего второго вопроса: не используйте этот метод CONVERT (), если вы работаете с таблицей большего размера. Более эффективный метод будет использовать что-то вроде

GROUP BY DATEADD(DAY, DATEDIFF(DAY, 0, < your datetime column >), 0) 

для группировки по дням, а также

GROUP BY DATEADD(MONTH, DATEDIFF(MONTH, 0, < your datetime column >), 0) 

для группировки по месяцам.

1 голос
/ 10 февраля 2010

1) Если я хочу вернуть первые два символа строки, что является лучшим / самым быстрым методом?

LEFT ('YourString', 2) ИМХО тем более естественно, более читабельно с точки зрениякричать и кричать это намерение.Я действительно не думаю, что это будет причиной низкой производительности - гораздо более вероятно, что удастся поразить плохую производительность из-за плохо сконструированного запроса, отсутствующих индексов и т. Д. Я бы просто придерживался того, что кажется естественным и самым простым.*2) Также, если у меня есть дата и я хочу группировать по дням, я буду использовать convert (varchar (10), getdate ()), так как наш формат БД в формате гггг / мм / дд, что даст «2010/02/10»если бы я хотел сгруппировать по месяцам, я бы использовал varchar (7) вместо этого, чтобы дать '2010/02'

. При преобразовании дат я бы всегда указывал последний параметр CONVERT, который является стилем.Например,

-- 112 = ISO format. This would give yyyyMM
SELECT CONVERT(VARCHAR(6), GETDATE(), 112) 

Обратите внимание, что это хороший пример того, что я сказал выше: другие области с большей вероятностью будут работать хуже.Если вы примените CONVERT к столбцу в предложении WHERE запроса, это предотвратит использование индекса для этого столбца.Поэтому вместо этого я бы изменил в запросе диапазон дат, указанный с начальной датой = началом месяца и конечной датой = 1-м днем ​​следующего месяца:

SELECT * 
FROM SomeTable
WHERE DateField >= @StartOfMonth AND DateField < @FirstDayOfNextMonth

Это будет использоватьиндекс на DateField, обеспечивающий лучшую производительность, чем подход CONVERT

1 голос
/ 10 февраля 2010

Результаты для части вычисления скалярного запроса идентичны при использовании LEFT(t.col, 2) и CONVERT(VARCHAR(2), t.col):

Estimated CPU Cost:       0.0283193
Estimated I/O Cost:       0
Estimated Number of Rows: 283193
Estimated Operator Cost:  0.028 (0%)

SQL Server 2005

Я предполагаю, что LEFT является синонимом CAST / CONVERT ...

0 голосов
/ 10 февраля 2010

проверить это:

DECLARE @x int
       ,@RunDate datetime
       ,@y  char(2)
       ,@z int
       ,@total int
       ,@tries int

SELECT @z=1,@total=0,@tries=20

WHILE @z<=@tries
BEGIN
    SELECT @RunDate=GETDATE(),@x=1,@z=@z+1
    WHILE @x<500000
    BEGIN
       SET @x=@x+1
       SELECT @x=@x+1,@y=LEFT('Chgffgjjx',2)
    END
    PRINT RIGHT(' '+CONVERT(varchar(2),@z-1),2)+' - LEFT() Took: '+CONVERT(varchar(20),datediff(ms,@RunDate,GETDATE()))+' milliseconds'
    SET @total=@total+CONVERT(varchar(20),datediff(ms,@RunDate,GETDATE()))
END
PRINT 'LEFT() average: '+CONVERT(varchar(20),@total/(1.0+@tries))
SELECT @z=1,@total=0,@tries=20
WHILE @z<=@tries
BEGIN

    SELECT @RunDate=GETDATE(),@x=1,@z=@z+1
    WHILE @x<500000
    BEGIN
       SET @x=@x+1
       SELECT @x=@x+1,@y=CONVERT(varchar(2),'Chgffgjjx')
    END
    PRINT RIGHT(' '+CONVERT(varchar(2),@z-1),2)+' - CONVERT() Took: '+CONVERT(varchar(20),datediff(ms,@RunDate,GETDATE()))+' milliseconds'
    SET @total=@total+CONVERT(varchar(20),datediff(ms,@RunDate,GETDATE()))
END
PRINT 'CONVERT() average: '+CONVERT(varchar(20),@total/(1.0+@tries))

ВЫВОД:

 1 - LEFT() Took: 563 milliseconds
 2 - LEFT() Took: 390 milliseconds
 3 - LEFT() Took: 406 milliseconds
 4 - LEFT() Took: 390 milliseconds
 5 - LEFT() Took: 390 milliseconds
 6 - LEFT() Took: 390 milliseconds
 7 - LEFT() Took: 393 milliseconds
 8 - LEFT() Took: 390 milliseconds
 9 - LEFT() Took: 390 milliseconds
10 - LEFT() Took: 486 milliseconds
11 - LEFT() Took: 686 milliseconds
12 - LEFT() Took: 453 milliseconds
13 - LEFT() Took: 390 milliseconds
14 - LEFT() Took: 406 milliseconds
15 - LEFT() Took: 403 milliseconds
16 - LEFT() Took: 410 milliseconds
17 - LEFT() Took: 560 milliseconds
18 - LEFT() Took: 546 milliseconds
19 - LEFT() Took: 593 milliseconds
20 - LEFT() Took: 390 milliseconds
LEFT() average: 429.7619047619047
 1 - CONVERT() Took: 440 milliseconds
 2 - CONVERT() Took: 513 milliseconds
 3 - CONVERT() Took: 393 milliseconds
 4 - CONVERT() Took: 453 milliseconds
 5 - CONVERT() Took: 390 milliseconds
 6 - CONVERT() Took: 406 milliseconds
 7 - CONVERT() Took: 420 milliseconds
 8 - CONVERT() Took: 406 milliseconds
 9 - CONVERT() Took: 390 milliseconds
10 - CONVERT() Took: 390 milliseconds
11 - CONVERT() Took: 406 milliseconds
12 - CONVERT() Took: 390 milliseconds
13 - CONVERT() Took: 626 milliseconds
14 - CONVERT() Took: 593 milliseconds
15 - CONVERT() Took: 423 milliseconds
16 - CONVERT() Took: 406 milliseconds
17 - CONVERT() Took: 450 milliseconds
18 - CONVERT() Took: 486 milliseconds
19 - CONVERT() Took: 406 milliseconds
20 - CONVERT() Took: 390 milliseconds
CONVERT() average: 417.9523809523809

они кажутся мне очень близкими

0 голосов
/ 10 февраля 2010

A1. LEFT конечно, как вы могли бы выполнять меньше работы, чем использовать функцию, которая явно делает только это?

A2. Не храните DATE s как varchars, сохраняйте их как даты и индексируйте их, это ускоряет процесс освещения заказов, и вы можете использовать DATEPART , чтобы получить определенные компоненты даты.

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