Медленный запрос - оптимизация

MapInfo, MapBasic
Ответить
2ndBr.Е.Ж.'n'E.B.
Новоприбывший
Сообщения: 13
Зарегистрирован: 04 июл 2010, 19:53
Репутация: 0

Медленный запрос - оптимизация

Сообщение 2ndBr.Е.Ж.'n'E.B. » 04 июн 2012, 01:04

Существует таблица формата:
Create Table TblValue_1(
f_value float
, i_col smallint
, i_row smallint
)
После заполнения таблицы делаю
Commit Table TblValue_1
Create Index On TblValue_1 (i_col)
Create Index On TblValue_1 (i_row)

Необходимо получить для каждой строки массив SomeArray() as float, состоящий элементов имеющих соседние значения i_col или i_row.
Код следующий:
Set Event Processing Off
for i = 1 to iMaxX
for j =1 to iMaxY
SELECT f_value "fValue" FROM TblValue_1WHERE (i_col >= (i - 1) AND i_col <= (i + 1) AND i_row >= (j- 1) AND i_row <= (j + 1)) INTO _tmp

SELECT Count(*) "iCountElement" FROM _tmp INTO _tmp2
Fetch First From _tmp2
iCountElements = _tmp2.iCountElement ' количество элементов
redim SomeArray(iCountElements)
Close Table _tmp2

Fetch First From _tmp
for i = 1 to iCountElements
SomeArray(i) = _tmp.fValue
Fetch Next From _tmp
next
Close Table _tmp
next
next
Set Event Processing On

При iMaxX = iMaxY = 5 выполнение кода подвисает на приличное время.
Как ускорить алгоритм? что делаю не так? Как проще получить количество строк в запросе?
Имеет ли смысл Set Event Processing Off...Set Event Processing On если к строкам таблицы будут привязаны объекты и таблица TblValue_1 будет показана слоем?

SergS
Активный участник
Сообщения: 120
Зарегистрирован: 14 апр 2011, 13:24
Репутация: 5
Откуда: Екатеринбург

Re: Медленный запрос - оптимизация

Сообщение SergS » 04 июн 2012, 06:28

2ndBr.Е.Ж.'n'E.B. писал(а):Как проще получить количество строк в запросе?
вот это:

Код: Выделить всё

SELECT Count(*) "iCountElement" FROM _tmp INTO _tmp2
 Fetch First From _tmp2
 iCountElements = _tmp2.iCountElement ' количество элементов
 Close Table _tmp2
заменить на

Код: Выделить всё

 iCountElements = Tableinfo(_tmp, TAB_INFO_NROWS)
2ndBr.Е.Ж.'n'E.B. писал(а):Имеет ли смысл Set Event Processing Off...Set Event Processing On если к строкам таблицы будут привязаны объекты и таблица TblValue_1 будет показана слоем?
в данном случае Set Event Processing Off/On вообще смысла не имеет, поскольку приведенный код никак не влияет на объекты, отображаемые на экране (есть ли гр. объекты у таблицыTblValue_1, или нет, показана она в окне карты или нет - не важно). Исключение м.б. только в том случае, если у вас (или у пользователя вышей программы) висит в работе 1, 2..... приложений, имеющих в свем составе SelChangedHandler, и призванных, по замыслу авторов, "удобно, логично, и красиво" расположить информацию в окне Mapinfo в соотвествии со сделанным выбором. Но, если, не пренебрегать в операторах Select... ключиком Noselect, то можно не обращать внимания.

Надеюсь, в примере - только часть алгоритма, потому как массив SomeArray каждый раз переписывается.

что касается самого алгритма.
переменная цикла i - используется и во внешнем цикле, и во внутреннем, результат - лень просчитывать, проще исправить ошибку и посмотроеть, что получится :)

Почему бы алгоритм не вывернуть. Сделать так:

Код: Выделить всё

Fetch First From TblValue_1
while not eot(TblValue_1)
    i = TblValue_1.i_col
    j = TblValue_1.j_row
    select * from TblValue_1 into _tmp_sel noselect where i_col in (i-1, i, i+1) and j_row in (j-1, j, j+1)
    iCountElements = tableinfo(_tmp_sel, TAB_NFO_NROWS)
    redim SomeArray( iCountElements )
    for k = 1 to iCountElements
          fetch rec k from _tmp_sel
          SomeArray( k ) = _tmp_sel.f_Value
    next
    close table _tmp_sel
    ' здесь я, надеюсь, массив SomeArray как то используется, потому что на следующей строке он перепишется
    ' в исходном алгоритме он переписывался бы в iMaxY*iMaxX раз больше  :) 
    Fetch next From TblValue_1
wend
ну, или я неправильно Вас понял. ИМХО - описание задачи не совсем соответствует приведенному вами коду

и последнее:
описание
Необходимо получить для каждой строки массив SomeArray() as float, состоящий элементов имеющих соседние значения i_col или i_row.
по-моему не очень эффективно реализуется оператором
WHERE (i_col >= (i - 1) AND i_col <= (i + 1) AND i_row >= (j- 1) AND i_row <= (j + 1))

2ndBr.Е.Ж.'n'E.B.
Новоприбывший
Сообщения: 13
Зарегистрирован: 04 июл 2010, 19:53
Репутация: 0

Re: Медленный запрос - оптимизация

Сообщение 2ndBr.Е.Ж.'n'E.B. » 04 июн 2012, 19:33

Спасибо большое. Скорость обработки возросла.
Код писался на форуме, в качестве примера, поэтому наименования переменных в циклах по невнимательности могут совпадать.
Существует необходимость поиска элементов в формате:

Код: Выделить всё

WHERE (i_col >= (i - k) AND i_col <= (i + k) AND i_row >= (j- k) AND i_row <= (j + k))
где k не всегда = 1, поэтому так и написал условие выборки
Пошел изучать справочник

Ответить

Вернуться в «MapInfo»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 2 гостя