[DB] Хочу убрать задержку выполнения запроса.

zorin29

Дано: БД с 2 таблицами: Games, Players.
Players: PlayerID, Name, Country, ...
Games: GameID, FirstID, SecondID, Score, Date, ...
Юзер как правило (95%) просматривает результат следующего запроса
SELECT GameID, A.Name as First, B.Name as Second, Score, Date, ...
FROM Games, Players as A, Players as B
WHERE A.PlayerID = FirstID AND B.PlayerID = SecondID AND <custom condition>, в частности часто custom condition-а вовсе нет.
1) Query.Open;
2) DBGrid.DataSource.DataSet := Query;
При выполнении соответствующих JOIN-ов (1) SQL-сервер тормозит секунд 10 (|Games| = 100 000, индексы построены). Затем юзер просматривает результат без торможений, подкачивая при необходимости данные.
Мне не нравится торможение в 10 секунд. Как бы его убрать, т.е. "размазать" во времени?
Я надумал вариант с расслоением Games:
SELECT ... FROM ... WHERE ... AND (GameID BETWEEN 10000 AND 12000)
Такие запросы выполняются мнговенно. Но в результате из-за Custom Condition в полученном DataSet-е может оказаться слишком мало записей... Как быть?
В принципе, можно пробовать сменить архитектуру базы, сменить SQL-engine, перестать использовать SQL и т.д. - свобода довольно большая.
Решение
CREATE VIEW GamesPlayers AS
SELECT GameID, A.Name as First, B.Name as Second, Score, Date, ...
FROM Games, Players as A, Players as B
WHERE A.PlayerID = FirstID AND B.PlayerID = SecondID
SELECT * FROM GamesPlayers WHERE CustomCondition
не работает, т.к. VIEW в случае нашего SQL-сервера создается только в момент SELECT, а потом удаляется - ускорения не получаем.
 

sakura

При выполнении соответствующих JOIN-ов (1)
Честно говоря, Delphi не знаю, но вопрос, как я понял, и не требует этого знания.
У меня вопрос к автору - какие JOIN-ы имеются ввиду? В смысле о чем речь, если в запросе нет JOIN?

sakura

К тому же не похоже, чтобы такой несложный запрос для относительно маленькой таблицы (100,000 строк) выполнялся 10 секунд. Может что-то с настройками базы? Или с индексами?

sakura

К тому же не понятно, зачем создавать вьюху. Нет никакой существенной разницы между тем, будешь ли ты получать нужную информация путем запроса или используешь select из вьюхи, которая основывается на этом запросе. При вызове SELECT my_view ... все равно будет выполнен запрос, который находится в my-view. Есть материализованные вьюхи - это другое дело. Но я не уверен, поможет ли тебе это...

zorin29

У меня вопрос к автору - какие JOIN-ы имеются ввиду? В смысле о чем речь, если в запросе нет JOIN?
Этот запрос эквивалентен
SELECT ...
FROM Games INNER JOIN Players AS A ON FirstID=A.PlayerID INNER JOIN Players AS B ON SecondID = B.PlayerID
WHERE CustomCondition
Поэтому я и написал для удобства JOIN.
Да, и запрос исполняется не над 100 000 табличкой Games, а над Games*Players*Players. Я понимаю, что это оптимизируется, но не до 100 000 все равно.

sakura

А какой размер PLAYERS?

skvoria

Слуш, а глянь-ка план выполнения запроса.
Когда-то видел такой косяк, типа бд-сервак составил план выполнения запроса для десятка записей и закешировал, на миллионе записей тормозило ессно.
100000 - небольшая цифра.
Что за сервер кстати?

sakura

SELECT ...
FROM Games INNER JOIN Players AS A ON FirstID=A.PlayerID INNER JOIN Players AS B ON SecondID = B.PlayerID
WHERE CustomCondition
А чем INNER JOIN отличается от серии AND-ов?
Чем этот запрос лучше/хуже того, что приведено в исходном вопросе?

zorin29

Сервер - NexusDB, не очень-то он знаменит, зато коряв
Настолько коряв, что план вып-я запроса не кеширует. Ну и неважно, впрочем, я сразу создал базу из 100к записей, а потом только начал слать запросы.
Почему-то у меня стойкое подозрение, что улучшить время выполнения ЭТОГО запроса не получится, по крайней мре в рамках Нексуса.
З.Ы. Таблица Games на диске весит 120 Мб, ибо там BLOB-ы. Но и при SELECT-е без блобов выполнение запроса хоть и ускоряется, но до 5 секунд, что все равно много.
А 100 000 - это для теста. Желательно, чтобы не тормозило на 3 миллионах записей.

skvoria

Нереальная жесть.
Поставь... ну хоть MySQL, уже проблем не будет.
Если со сменой движка БД проблемы - кажися дальше только денормализация.

zorin29

С точки зрения логики - ничем не отличается, т.к. результат тот же.
С точки зрения НОРМАЛЬНОГО оптимизатора запросов - тоже ничем, т.к. он должен понимать, что это одно и то же.
Мой сервер, кстати, перед выполнением запроса с INNER JOIN-ами превращает их в WHERE ... AND ..., т.е. в первый вариант.

zorin29

А клиентскую часть модифицировать не стоит? В первом посте написан огрызок соответствующей идеи... Ведь результат запроса нужен именно юзеру, и нужен не сразу весь, а по частям, чтобы на него глядеть.
Завтра буду пробовать на другом БД-движке, но штука в том, что они, гады, платные А нужно не абы какой, а чтобы встраивался в exe-шник.

Dasar

такой запрос за сколько делается?
SELECT GameID, FirstId, SecondId, Score, Date, ...
FROM Games
where <custom condition>

sakura

Завтра буду пробовать на другом БД-движке, но штука в том, что они, гады, платные
Oracle - бесплатный

zorin29

3 секунды, зараза такая, он делается.
Но именно с Nexus-ом можно расчеты над ОДНОЙ таблицей перенести на клиента (т. наз. Live Request). Я с ним мало экспериментировал, но похоже, что он как раз "размазывает" эти три секунды по времени, пока юзер давит кнопку вниз
Но в случае JOIN-а ничего не катит. Сначала сервер все равно делает JOIN, на что тратит основное время.
P.S. ушел часа на два.

skvoria

результат запроса нужен именно юзеру, и нужен не сразу весь, а по частям
Хм, я наверное не слишком правильно понял...
По логике работы приложения ты можешь сделать разбиение на страницы? если да - то вытаскиваешь общее количество записей (кстати, посмотри время выполнения) и делишь на кол-во записей на "страницу".
Или ты хочешь все равно подгрузить все записи, но как бы частями?

zorin29

Я смотрел уже - общее количество записей считается тоже секунды за 2. Да и не очень понятно, как загрузить, скажем, "записи с 10000 по 11000 из такого-то запроса" Есть, конечно
SELECT ... WHERE ... LIMIT 10000,1000
, но а) эта конструкция не поддерживается столь любимым Нексусом, б) подозреваю, что все равно запрос выполняется целиком.

sbs-66

ты б хоть указал на то, какие в таблицах поля и какие у них ключи. А то это всё какие-то теоретизирования...
По делу - у тебя или по какой-то причине ключи не работают, или БД жутко тупая.
Оставить комментарий
Имя или ник:
Комментарий: