Показать сообщение отдельно
Старый 28.07.2004, 14:22   #2  
Vadik is offline
Vadik
Модератор
Аватар для Vadik
Лучший по профессии 2017
Лучший по профессии 2015
 
3,631 / 1853 (69) ++++++++
Регистрация: 18.11.2002
Адрес: гражданин Москвы
Цитата:
Изначально опубликовано psv
Я не стал бы делать столь однозначные выводы на основе одного примера неграмотного использования хинтов.
Перечитал еще раз - однозначных выводов не вижу, вижу информацию для размышления. Насчет одного примера - могу подкинуть еще, их есть у меня, не жалко

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

Цитата:
Пользоваться ими нужно в крайнем случае, но иногда это дает значительный выигрыш.
я в последнее время куда ни ткнусь - везде эти "крайние случаи" (хинты), а выигрыш.. мягко говоря, сомнительный.

для затравки:

MSSQL SP3a, аксапта 3.0 SP3CIS

игрушечная БД

Заказы \ Функции \ Создание строк

имею
InventTable - порядка 10000 строк, InventSum - 120000 строк, InventDim - 100000 строк

смотрим executeQuery на InventTable в SalesQuickQuote

PHP код:
    if (inventTable_ds.queryRun())
        
query inventTable_ds.queryRun().query();
    else
        
query inventTable_ds.query();

    
query.forceSelectOrder(true);
    
query.datasourceTable(tableNum(inventDim)).addSortIndex(IndexNum(InventDimDimIdIdx));
    
query.datasourceTable(tableNum(inventDim)).indexIsHint(true);
    
query.datasourceTable(tableNum(inventSum)).addSortIndex(IndexNum(InventSumItemDimIdx));
    
query.datasourceTable(tableNum(inventSum)).indexIsHint(true); 
ловим запрос и мучаем его в QA:

вот это - оригинальный (весьма) запрос:

SELECT A.ITEMID,SUM(B.AVAILPHYSICAL),MIN(B.INVENTDIMID),B.ITEMID,C.INVENTLOCATIONID
FROM INVENTTABLE A(NOLOCK) ,INVENTSUM B(INDEX(I_174ITEMDIMIDX) NOLOCK) ,INVENTDIM C(INDEX(I_698DIMIDIDX) NOLOCK)
WHERE (A.DATAAREAID='bmd') AND ((B.DATAAREAID='bmd') AND (A.ITEMID=B.ITEMID)) AND ((C.DATAAREAID='bmd') AND (B.INVENTDIMID=C.INVENTDIMID))
GROUP BY A.ITEMID,B.ITEMID,C.INVENTLOCATIONID
ORDER BY A.ITEMID,B.ITEMID,C.INVENTLOCATIONID
OPTION(FAST 1,FORCE ORDER)

(9717 row(s) affected)

Table 'INVENTTABLE'. Scan count 2, logical reads 838, physical reads 33, read-ahead reads 821.
Table 'INVENTSUM'. Scan count 2, logical reads 112409, physical reads 1011, read-ahead reads 4579.
Table 'INVENTDIM'. Scan count 2, logical reads 102426, physical reads 876, read-ahead reads 745.

SQL Server Execution Times:
CPU time = 17891 ms, elapsed time = 28548 ms.

убираем хинты

SELECT A.ITEMID,SUM(B.AVAILPHYSICAL),MIN(B.INVENTDIMID),B.ITEMID,C.INVENTLOCATIONID
FROM INVENTTABLE A(NOLOCK) ,INVENTSUM B(NOLOCK) ,INVENTDIM C(NOLOCK)
WHERE (A.DATAAREAID='bmd') AND ((B.DATAAREAID='bmd') AND (A.ITEMID=B.ITEMID)) AND ((C.DATAAREAID='bmd') AND (B.INVENTDIMID=C.INVENTDIMID))
GROUP BY A.ITEMID,B.ITEMID,C.INVENTLOCATIONID
ORDER BY A.ITEMID,B.ITEMID,C.INVENTLOCATIONID

(9717 row(s) affected)

Table 'INVENTDIM'. Scan count 2, logical reads 1055, physical reads 0, read-ahead reads 1055.
Table 'INVENTTABLE'. Scan count 2, logical reads 40, physical reads 2, read-ahead reads 39.
Table 'INVENTSUM'. Scan count 2, logical reads 4651, physical reads 0, read-ahead reads 4658.

SQL Server Execution Times:
CPU time = 3891 ms, elapsed time = 8697 ms.

для чистоты эксперимента, ясное дело, кэш перед запуском обоих запросов чистится

сравниваем execution times, logical reads, physical reads, начинаем плеваться в монитор

примеров таких - вагон и маленькая тележка