Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Медленные запросы  [new]
Неместный_123
Guest
Уважаемые коллеги, прошу высказаться по следующему вопросу.

Есть 2 таблицы.
В первой хранится заголовок некого журнала. Основные поля - Дата и ID.
Во второй - строки. Поля - ссылка на ID журнала (ID_Header), какое-нибудь количество (сумма, объем...) - пусть будет Qty, некий признак данной строки журнала, например код сотрудника ID_Empl.
У нас в системе в нескольких местах применяется такая структура данных.

Индексы (из относящихся к делу)
на первой таблице:
- ID (уникальный, кластерный)
- Дата + ID
На второй:
- ID_Header + ID_Empl (уникальный, кластерный)
- ID_Empl + ID_Header

Статистика обновлена.

В первой таблице записей порядка миллиона. Во второй один-два миллиона. Вообще строк в журнале 1-2, крайне редко 3.

Часто требуется:
1. Выбрать все записи за интервал дат, относящиеся к определенному ID_Empl.
select * FROM line A, header B
WHERE A.ID_Empl = _id AND line.ID_Header = header.ID
AND B.Дата >= _from AND B.Дата <= _to

2. Посчитать общее Qty по данному ID_Empl за интервал дат.
SELECT SUM(A.Qty)
FROM line A
WHERE A.ID_Empl = _id
AND EXISTS (SELECT 'X' FROM header B WHERE B.ID=A.ID_Header AND B.Дата >= _from AND B.Дата <= _to)

И то и другое работает на мой взгляд крайне медленно. Т.е. каждый запрос в среднем 1-2 секунды при выборке за месяц. В месяц от 0 до 50 журналов должны попадать в выборку. В среднем наверное 15. Некоторые запросы исполняются вообще по минуте.

Вопрос. Такая структура данных в принципе неправильная, или индексов не хватает, или запрос плохой?
27 июл 11, 17:23    [11035648]     Ответить | Цитировать Сообщить модератору
 Re: Медленные запросы  [new]
iap
Member

Откуда: Москва
Сообщений: 47144
Неместный_123,

1. обычно переменные в MSSQL пишут, начиная с символа '@', а не '_'.
Может, у Вас не MSSQL?
2. Синтаксис первого запроса использует запятую, то есть устаревший аналог CROSS JOIN. Лучше, наверно, JOIN.
3. Зачем во втором запросе EXISTS вместо JOIN? Непонятно.
27 июл 11, 17:35    [11035725]     Ответить | Цитировать Сообщить модератору
 Re: Медленные запросы  [new]
Неместный_123
Guest
iap,

MSSQL. Это "псевдокод". Но join у нас делается именно так. Система генерит код на SQL.

Насчет Exists join. Сначала там был просто join. Переделали на exists в надежде что станет быстрее. Пожалуй сравним внимательно эти 2 варианта.
27 июл 11, 18:21    [11036052]     Ответить | Цитировать Сообщить модератору
 Re: Медленные запросы  [new]
kapelan
Member

Откуда: хутор БольшойБугор
Сообщений: 726
Неместный_123,
криминала в коде нету,
попробуйте так:
select * 
FROM header B
JOIN line A
  ON  a.ID_Header = b.ID
 AND  A.ID_Empl = @id 
WHERE  B.Data >= @from AND B.Data <= @to
  OPTION (FORCE ORDER )
27 июл 11, 18:34    [11036108]     Ответить | Цитировать Сообщить модератору
 Re: Медленные запросы  [new]
Неместный_123
Guest
kapelan

Почему так?
План запроса будет такой же, как без option, в том случае, когда хидеров в указанном интервале дат согласно статистике "мало".
А если наоборот "много", план будет хуже чем сервер сам рассчитает. Разве нет?
28 июл 11, 12:20    [11038803]     Ответить | Цитировать Сообщить модератору
 Re: Медленные запросы  [new]
kapelan
Member

Откуда: хутор БольшойБугор
Сообщений: 726
Неместный_123
kapelan

Почему так?
План запроса будет такой же, как без option, в том случае, когда хидеров в указанном интервале дат согласно статистике "мало".
А если наоборот "много", план будет хуже чем сервер сам рассчитает. Разве нет?

все правильно,
поетому написал попробуйте
28 июл 11, 19:18    [11041631]     Ответить | Цитировать Сообщить модератору
 Re: Медленные запросы  [new]
Yuriy Petrov
Member

Откуда:
Сообщений: 91
Неместный_123
Уважаемые коллеги, прошу высказаться по следующему вопросу.

Есть 2 таблицы.
В первой хранится заголовок некого журнала. Основные поля - Дата и ID.
Во второй - строки. Поля - ссылка на ID журнала (ID_Header), какое-нибудь количество (сумма, объем...) - пусть будет Qty, некий признак данной строки журнала, например код сотрудника ID_Empl.
У нас в системе в нескольких местах применяется такая структура данных.

Индексы (из относящихся к делу)
на первой таблице:
- ID (уникальный, кластерный)
- Дата + ID
На второй:
- ID_Header + ID_Empl (уникальный, кластерный)
- ID_Empl + ID_Header

Статистика обновлена.

В первой таблице записей порядка миллиона. Во второй один-два миллиона. Вообще строк в журнале 1-2, крайне редко 3.

Часто требуется:
1. Выбрать все записи за интервал дат, относящиеся к определенному ID_Empl.
select * FROM line A, header B
WHERE A.ID_Empl = _id AND line.ID_Header = header.ID
AND B.Дата >= _from AND B.Дата <= _to

2. Посчитать общее Qty по данному ID_Empl за интервал дат.
SELECT SUM(A.Qty)
FROM line A
WHERE A.ID_Empl = _id
AND EXISTS (SELECT 'X' FROM header B WHERE B.ID=A.ID_Header AND B.Дата >= _from AND B.Дата <= _to)

И то и другое работает на мой взгляд крайне медленно. Т.е. каждый запрос в среднем 1-2 секунды при выборке за месяц. В месяц от 0 до 50 журналов должны попадать в выборку. В среднем наверное 15. Некоторые запросы исполняются вообще по минуте.

Вопрос. Такая структура данных в принципе неправильная, или индексов не хватает, или запрос плохой?

Если это возможно, я бы схему поменял :)
Например:
create table Header (
   RecDate datetime primary key,         -- ведь одновременно две записи не запишут.(?)
   Id int,                     -- значимый или identity, едино
   ...
);

create table Lines (
   RecDate datetime,
   EmplId int,
   ...
   primary key (RecDate, EmplId) clustered
);

create nonclustered index idxLines on Lines (EmplId);    -- в нем уже есть поле даты
Ну и запросы упростятся :)
28 июл 11, 19:51    [11041709]     Ответить | Цитировать Сообщить модератору
 Re: Медленные запросы  [new]
Crimean
Member

Откуда:
Сообщений: 13147
а чо в планах-то?
28 июл 11, 20:42    [11041838]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить