|
Как использовать результат запроса Select в качестве массива?
|
|||
---|---|---|---|
#18+
С базой данных работаю из Delphi. В таблице порядка 350 тыс.записей. При выборке получается около 1000 записей. Результаты хочу просмотреть в TDrawGrid. Отдельный массив создавать и загонять результат в него считаю не правильным, т.к. он уже существует, да и смысла тратить время на это тоже нет. Проблема 1. Для подсчета колличества записей нужно прогонять весь массив. Проблема 2. Для отображения записи с №_n опять же необходимо прогонять с начала. И когда отображаются элементы с номерами около 500 уже становится заметно как долго идет поиск элемента с номером (используется sqlite3_next). Есть какая-то альтернатива (не используя sqLite3_next) для обращения к результатам выборки как к массиву, например Элемент[номер элемента]? Или быть может возможно получить указатели на каждый элемент и работать чисто с указателями? Ребята помогите чем сможете. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.01.2011, 17:40 |
|
Как использовать результат запроса Select в качестве массива?
|
|||
---|---|---|---|
#18+
Манюшкин ВладимирС базой данных работаю из Delphi. В таблице порядка 350 тыс.записей. При выборке получается около 1000 записей. Результаты хочу просмотреть в TDrawGrid. Отдельный массив создавать и загонять результат в него считаю не правильным, т.к. он уже существует, да и смысла тратить время на это тоже нет.Вот это и есть твоя главная ошибка. Вытаскиваешь результат select в свой собственный массив и с ним работаешь. Все проблемы исчезнут. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.01.2011, 18:48 |
|
Как использовать результат запроса Select в качестве массива?
|
|||
---|---|---|---|
#18+
Манюшкин ВладимирОтдельный массив создавать и загонять результат в него считаю не правильным, т.к. он уже существует... ?! Что же это за массив такой, чтобы... Манюшкин Владимир1. Для подсчета колличества записей нужно прогонять весь массив. 2. Для отображения записи с №_n опять же необходимо прогонять с начала. Не смог найти что такое sqlite3_next, но это явно не очень эффективная штука. Обычный TStringList должен справиться быстрее. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.01.2011, 21:18 |
|
Как использовать результат запроса Select в качестве массива?
|
|||
---|---|---|---|
#18+
1) Альтернативы нет. У sqlite нет понятия "rowset fetching". Выборка идет по одной записи. Догадайся почему ... :) 2) TDrawGrid - на хрена велосипед изобретать, почему тот же TDBGrid не использовать ? Ну плюс один из сторонних продуктов. Из бесплатных - Aducom http://www.aducom.com ... |
|||
:
Нравится:
Не нравится:
|
|||
16.01.2011, 21:20 |
|
Как использовать результат запроса Select в качестве массива?
|
|||
---|---|---|---|
#18+
Dmitry Arefiev2...на хрена велосипед изобретать, почему тот же TDBGrid не использовать Наверное, есть какая-нибудь причина. 1. Альтернатива должна быть. Если есть какой-то "массив", то в delphi его по меньшей мере можно завернуть в объект, получить для него (один раз - при каждой выборке) свойство count и даже обеспечить доступ к результатам выборки как к массиву, например Элемент[номер элемента] Или даже получить указатели на каждый элемент и работать чисто с указателями. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.01.2011, 21:50 |
|
Как использовать результат запроса Select в качестве массива?
|
|||
---|---|---|---|
#18+
Kolyvpro, SQLite3_step ... |
|||
:
Нравится:
Не нравится:
|
|||
17.01.2011, 03:23 |
|
Как использовать результат запроса Select в качестве массива?
|
|||
---|---|---|---|
#18+
Dmitry Arefiev, писал 1) Альтернативы нет. У sqlite нет понятия "rowset fetching". Выборка идет по одной записи. Догадайся почему ... :) Я догадываюсь почему, но при этом догадываюсь, что результат работы SELECT - наверняка тоже указатели на данные в базе данных, т.к. если бы и SELECT создавал отдельную область памяти и туда копировал всю выборку, тогда он врятли бы достиг тех скоростей, которые мы видим сегодня. Отсюда следует почему бы не использовать нам эти указатели, но как? ... |
|||
:
Нравится:
Не нравится:
|
|||
17.01.2011, 03:28 |
|
Как использовать результат запроса Select в качестве массива?
|
|||
---|---|---|---|
#18+
White OwlМанюшкин ВладимирС базой данных работаю из Delphi. В таблице порядка 350 тыс.записей. При выборке получается около 1000 записей. Результаты хочу просмотреть в TDrawGrid. Отдельный массив создавать и загонять результат в него считаю не правильным, т.к. он уже существует, да и смысла тратить время на это тоже нет.Вот это и есть твоя главная ошибка. Вытаскиваешь результат select в свой собственный массив и с ним работаешь. Все проблемы исчезнут. Мне просто совесть не позваляет дублировать данные, но если другого варианта найдено не будет, придется дублировать. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.01.2011, 03:32 |
|
Как использовать результат запроса Select в качестве массива?
|
|||
---|---|---|---|
#18+
Манюшкин ВладимирОтсюда следует почему бы не использовать нам эти указатели, но как? Это надо искать в исходниках SQLite. Например смотри как sqlite3_column_double устроена. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.01.2011, 07:06 |
|
Как использовать результат запроса Select в качестве массива?
|
|||
---|---|---|---|
#18+
Манюшкин ВладимирSQLite3_step Так вон оно, что, Михалыч... Результат, который возвращает SQLite3_step не берется напрямую из готового массива: sqlite.orgThis routine is used to evaluate a prepared statement that has been previously created by the sqlite3_prepare() interface. The statement is evaluated up to the point where the first row of results are available. Иными словами, после вызова SQLite3_step, данные предыдущего вызова нигде не остаются, если только их не сохранит приложение. Манюшкин ВладимирМне просто совесть не позваляет дублировать данные Так что, никакого дублирования данных нет (1) "Массив", о котором ты говоришь, создается с помощью встроенного wrapper'a sqlite3_get_table. Он сам выделяет память под всю выборку и разрешает использовать ее в приложении, пока она не освободится вызовом sqlite3_free_table (2) Примерно так. ---------- (1) Вернее, в момент переноса записи в свой массив каждая строка будет (может быть) продублирована, но только до очередного вызова SQLite3_step. (2) Результаты sqlite3_get_table (или, по мере выполнения, результаты SQLite3_step) можно сохранять в StringList (раз уж все равно выводить в DrawGrid): field_name_1 field_name_2 row1_field1_value row1_field2_value row2_field1_value row2_field2_value etc. В нем легко получить доступ к значениям полей как к массиву, например Элемент[номер элемента]. Для этого нужно всего-то 2 дополнительных свойства (переменных), в которых сохранятся RowCount и FieldCount. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.01.2011, 07:20 |
|
Как использовать результат запроса Select в качестве массива?
|
|||
---|---|---|---|
#18+
Манюшкин Владимирно при этом догадываюсь, что результат работы SELECT - наверняка тоже указатели на данные в базе данных, т.к. если бы и SELECT создавал отдельную область памяти и туда копировал всю выборку, тогда он врятли бы достиг тех скоростей, которые мы видим сегодня. Отсюда следует почему бы не использовать нам эти указатели, но как?Нет, не правильно догадываешься. На какую по твоему область памяти будет "создан указатель" если делается выборка из нескольких таблиц, да с функциями, да с агрегатами... Если б выборки делались только из таблиц напрямую, тогда твоя мечта о волшебных указателях на внутренние массивы имела бы основание. Но в реальности это только мечта. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.01.2011, 07:26 |
|
Как использовать результат запроса Select в качестве массива?
|
|||
---|---|---|---|
#18+
KolyvproМанюшкин ВладимирSQLite3_step Так вон оно, что, Михалыч... Результат, который возвращает SQLite3_step не берется напрямую из готового массива: sqlite.orgThis routine is used to evaluate a prepared statement that has been previously created by the sqlite3_prepare() interface. The statement is evaluated up to the point where the first row of results are available. Иными словами, после вызова SQLite3_step, данные предыдущего вызова нигде не остаются, если только их не сохранит приложение. Манюшкин ВладимирМне просто совесть не позваляет дублировать данные Так что, никакого дублирования данных нет (1) "Массив", о котором ты говоришь, создается с помощью встроенного wrapper'a sqlite3_get_table. Он сам выделяет память под всю выборку и разрешает использовать ее в приложении, пока она не освободится вызовом sqlite3_free_table (2) Примерно так. ---------- (1) Вернее, в момент переноса записи в свой массив каждая строка будет (может быть) продублирована, но только до очередного вызова SQLite3_step. (2) Результаты sqlite3_get_table (или, по мере выполнения, результаты SQLite3_step) можно сохранять в StringList (раз уж все равно выводить в DrawGrid): field_name_1 field_name_2 row1_field1_value row1_field2_value row2_field1_value row2_field2_value etc. В нем легко получить доступ к значениям полей как к массиву, например Элемент[номер элемента]. Для этого нужно всего-то 2 дополнительных свойства (переменных), в которых сохранятся RowCount и FieldCount. 1. Занимаюсь SQLite'м (и вообще SQL ) с 4 января 2011г. За это время все таки удалось выяснить, где и как используется QLite3_step. Вот выдержка из описания функций SQLite3.DLL для Delphi: function TSQLiteStatement.Next: Boolean; var r: Integer; begin r := sqlite3_step(FStmt); case r of SQLITE_ROW: Result := true; SQLITE_DONE: Result := false; else FSQLite.RaiseError('fail to fetch row'); Result := false; end; end; после того как она вернет отрицание - будет означать, что конец массива, но данные ни куда не деваются. Если сделать sq_check(sqlite3_reset(FStmt)) то можно снова этот массив перебирать опять же с помощь SQLite3_step. 2. Насколько мне известно SQLite3_get_table использует ту же SQLite3_step. 3. Если бы я не сомневался, я бы уже давно все в StringList загнал. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.01.2011, 17:32 |
|
Как использовать результат запроса Select в качестве массива?
|
|||
---|---|---|---|
#18+
White OwlМанюшкин Владимирно при этом догадываюсь, что результат работы SELECT - наверняка тоже указатели на данные в базе данных, т.к. если бы и SELECT создавал отдельную область памяти и туда копировал всю выборку, тогда он врятли бы достиг тех скоростей, которые мы видим сегодня. Отсюда следует почему бы не использовать нам эти указатели, но как?Нет, не правильно догадываешься. На какую по твоему область памяти будет "создан указатель" если делается выборка из нескольких таблиц, да с функциями, да с агрегатами... Если б выборки делались только из таблиц напрямую, тогда твоя мечта о волшебных указателях на внутренние массивы имела бы основание. Но в реальности это только мечта. Хочу заметить, что выборка особенно в тексте не всегда делается с функциями, агрегатами и пр., а таких случаев море , поэтому должен предположить, что в этих случаях смысла дублировать данные нет, а тем более если речь идет об оптимизации, а SQLite насколько я понимаю, именно поэтому и работает быстро потому что его работа оптимизирована. А текст в полях SQLite может быть даже по нескольку килобайт. Вопрос: Зачем его копировать в результат выборки, если можно просто запомнить указатель на него (с позиций программистов SQLite). К вопросу о нескольких таблицах- да хоть из миллиона таблиц - запомнил указатель на конкретное поле (опять же с позиции разработчиков SQLite) и когда спросят, тогда уж и прочитал данные откуда треба, и выдал в результат запрашивающей функции. Я понимаю, что здесь умников хватает, но - давайте по сути, есть решение обсуждаем, нет, значит зачем о каких-то там "волшебных указателях" говорить. И нет у меня никакой мечты об волшебных указателях. А есть реальные обоснованные предположения. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.01.2011, 17:45 |
|
Как использовать результат запроса Select в качестве массива?
|
|||
---|---|---|---|
#18+
Манюшкин Владимир1. Занимаюсь SQLite'м (и вообще SQL ) с 4 января 2011г. За это время все таки удалось выяснить, где и как используется QLite3_step. Вот выдержка из описания функций SQLite3.DLL для Delphi: Код: plaintext
Если сделать sq_check(sqlite3_reset(FStmt)) то можно снова этот массив перебирать опять же с помощь SQLite3_step. 2. Насколько мне известно SQLite3_get_table использует ту же SQLite3_step. 3. Если бы я не сомневался, я бы уже давно все в StringList загнал. 1. Уточнение. Вот выдержка из описания sqlite API (не для delphi, а для всех): sqlite.orgThe sqlite3_reset() function is called to reset a prepared statement object back to its initial state , ready to be re-executed Это означает, что после вызова sqlite3_reset prepared statement (FStmt) сбрасывается и получение данных происходит заново - сначала, как будто в первый раз. Из описания TSQLiteStatement.Next вовсе не следует, что возврат false означает конец массива. False на самом деле говорит, что sqlite_step сообщает о том, что в базе кончились строки, отвечающие запросу. К этом времени никакого "массива" и никаких "данных" в нем нет. Они перестают существовать сразу после передачи их в приложение. 2. Действительно, SQLite3_get_table использует ту же SQLite3_step (я ж сказал, что это враппер). Отличие только в том, что функция SQLite3_get_table (и только она!) действительно помещает всю выборку в массив, откуда ее можно достать без использования sqlite API. 3. Сейчас я развею все сомнения. 3.1. Начнем с того, что sqlite - это как бы мост. Представим себе оптовую базу и магазин на разных берегах реки. Ты (владелец магазина) не станешь хранить товар, полученный на базе, на мосту? Во-первых, для этого у тебя есть подсобка, откуда товар выдать покупателю проще и быстрее. Во-вторых, сваленный на мосту товар будет мешать проходу. Так-что экономия на доставке (не до магазина, а всего лишь до моста!) и свободное место в подсобке не дадут ожидаемой выгоды. sqlite предназначена для доступа приложений к БД. Для хранения данных приложений, которые ее использует, она не предназначена. Поэтому предполагается, что приложение, получившее данные из БД должно их хранить в своей памяти. Поэтому sqlite, как только сообщает эти данные приложению, сразу их "забывает". Я уже говорил, что к тому времени, как приложение получило строку из sqlite, ее копии в "памяти библиотеки" не остается. 3.2. Для особо продвинутых пользователей есть исходный код sqlite и документация, в т.ч. "для тех, кто хочет хакнуть sqlite". Я так понимаю, что времени на ознакомление с ней у тебя еще не было, поэтому рассказываю: 3.2.1. Ты не до конца правильно понимаешь механизм работы sqlite3_step (см. п.1). На самом деле это враппер для private функции sqlite3step. Последняя, вопреки ожиданиям, не обращается к массиву, а запускает на выполнение sqlite3VdbeExec - виртуальный движок БД. Prepared_Statement (FStmt) - по-моему, указатель на этот движок. sqlite3VdbeExec - очень длинная функция, которая как бы выполняет некий "код", как бы скомпилированный при обработке нашего запроса. Но и эта функция (надо же!) заканчивает выполнение после того, как сформирует одну(!) запись, отвечающую условиям выборки. Затем выполнение возвращается в sqlite3_step, откуда можно забрать результат работы виртуального движка. Такая цепочка (sqlite3_step -> sqlite3step -> sqlite3VdbeExec) нужна для автоматической перекомпиляции запроса, определения возвращаемого значения - в общем, для адекватной передачи запрошенной информации пользователю (приложению). 3.2.2. Между тем, логика подсказывает, что White OWl ошибается (или специально вводит нас в заблуждение насчет "волшебных указателей". Действительно, для того, чтобы, например, выдать одну строку (с функциями, аггрегатами, из нескольких таблиц и даже БД) с сортировкой, надо сначала получить все(!) остальные строки. Иначе как тогда их упорядочить?! Поэтому "волшебные указатели" просто обязаны где-то быть! И они есть!!! В описании работы виртуального движка БД есть упоминание объекта Rowset, который может использоваться для сбора и сортировки (?) записей. Значит нам достаточно 1. ввести глобальные переменные Код: plaintext
2.создать свою экспортируемую функцию sqlite3_i_want_it_all[ (списываем ее с sqlite3step), которая дополнительно будет - устанавливать значение manushkin_solution в true, - вызывать sqlite3VdbeExec и - возвращать указатель на manushkin_array. 3. sqlite3VdbeExec подправим только слегка: - если manushkin_solution=true, то принудительно создаем объект rowset (в обычном случае он используется не всегда) и - в конце исполнения sqlite3VdbeExec (когда данные уже собраны, отсортированы и первая строка подготовлена к отправке в приложение) при manushkin_solution=true устанавливаем manushkin_array=@rowset, а rs (код результата исполнения sqlite3VdbeExec) = 666. - запрещаем дальнейшую работу с rowset, приостанавливаем виртуальный движок, чтобы он ненароком не освободил память, которая нам понадобится, не сбросил курсор и т.п. 4. Наша функция sqlite3_i_want_it_all, получив результат sqlite3VdbeExec=666, заканчивает выполнение возвращением приложению ссылки на manushkin_array, с которым мы работаем из delphi без дублирования данных. 5. Для работы с массивом (приведение его в читаемые данные) можно перевести на pascal функции, которые уже есть в sqlite.dll или экспортировать их. 6. После того, как мы сделали с данными все, что хотели, разрешаем окончание исполнения sqlite3VdbeExec, чтобы она освободила память и поудаляла все объекты, которые стали ненужны. И НИКАКОГО ДУБЛИРОВАНИЯ:) А еще можно сделать так, чтобы sqlite Использовала память, выделенную приложением (по-моему, в 3 версии это допускается) и, отслеживая ее состояние, получать данные напрямую в DrawGrid:) -- В общем, волшебные указатели иногда существуют, просто разработчик sqlite их тщательно скрыл, - SQLite, насколько я понимаю, именно поэтому и работает быстро. А твое приложение будет работать настолько быстро, насколько ты сам сумеешь его научить. ... |
|||
:
Нравится:
Не нравится:
|
|||
18.01.2011, 14:58 |
|
Как использовать результат запроса Select в качестве массива?
|
|||
---|---|---|---|
#18+
KolyvproМанюшкин Владимир1. Занимаюсь SQLite'м (и вообще SQL ) с 4 января 2011г. За это время все таки удалось выяснить, где и как используется QLite3_step. Вот выдержка из описания функций SQLite3.DLL для Delphi: Код: plaintext
Если сделать sq_check(sqlite3_reset(FStmt)) то можно снова этот массив перебирать опять же с помощь SQLite3_step. 2. Насколько мне известно SQLite3_get_table использует ту же SQLite3_step. 3. Если бы я не сомневался, я бы уже давно все в StringList загнал. 1. Уточнение. Вот выдержка из описания sqlite API (не для delphi, а для всех): sqlite.orgThe sqlite3_reset() function is called to reset a prepared statement object back to its initial state , ready to be re-executed Это означает, что после вызова sqlite3_reset prepared statement (FStmt) сбрасывается и получение данных происходит заново - сначала, как будто в первый раз. Из описания TSQLiteStatement.Next вовсе не следует, что возврат false означает конец массива. False на самом деле говорит, что sqlite_step сообщает о том, что в базе кончились строки, отвечающие запросу. К этом времени никакого "массива" и никаких "данных" в нем нет. Они перестают существовать сразу после передачи их в приложение. 2. Действительно, SQLite3_get_table использует ту же SQLite3_step (я ж сказал, что это враппер). Отличие только в том, что функция SQLite3_get_table (и только она!) действительно помещает всю выборку в массив, откуда ее можно достать без использования sqlite API. 3. Сейчас я развею все сомнения. 3.1. Начнем с того, что sqlite - это как бы мост. + Представим себе оптовую базу и магазин на разных берегах реки. Ты (владелец магазина) не станешь хранить товар, полученный на базе, на мосту? Во-первых, для этого у тебя есть подсобка, откуда товар выдать покупателю проще и быстрее. Во-вторых, сваленный на мосту товар будет мешать проходу. Так-что экономия на доставке (не до магазина, а всего лишь до моста!) и свободное место в подсобке не дадут ожидаемой выгоды. sqlite предназначена для доступа приложений к БД. Для хранения данных приложений, которые ее использует, она не предназначена. Поэтому предполагается, что приложение, получившее данные из БД должно их хранить в своей памяти. Поэтому sqlite, как только сообщает эти данные приложению, сразу их "забывает". Я уже говорил, что к тому времени, как приложение получило строку из sqlite, ее копии в "памяти библиотеки" не остается. 3.2. Для особо продвинутых пользователей есть исходный код sqlite и документация, в т.ч. "для тех, кто хочет хакнуть sqlite". Я так понимаю, что времени на ознакомление с ней у тебя еще не было, поэтому рассказываю: 3.2.1. Ты не до конца правильно понимаешь механизм работы sqlite3_step (см. п.1). На самом деле это враппер для private функции sqlite3step. Последняя, вопреки ожиданиям, не обращается к массиву, а запускает на выполнение sqlite3VdbeExec - виртуальный движок БД. Prepared_Statement (FStmt) - по-моему, указатель на этот движок. sqlite3VdbeExec - очень длинная функция, которая как бы выполняет некий "код", как бы скомпилированный при обработке нашего запроса. Но и эта функция (надо же!) заканчивает выполнение после того, как сформирует одну(!) запись, отвечающую условиям выборки. Затем выполнение возвращается в sqlite3_step, откуда можно забрать результат работы виртуального движка. Такая цепочка (sqlite3_step -> sqlite3step -> sqlite3VdbeExec) нужна для автоматической перекомпиляции запроса, определения возвращаемого значения - в общем, для адекватной передачи запрошенной информации пользователю (приложению). 3.2.2. Между тем, логика подсказывает, что White OWl ошибается (или специально вводит нас в заблуждение насчет "волшебных указателей". Действительно, для того, чтобы, например, выдать одну строку (с функциями, аггрегатами, из нескольких таблиц и даже БД) с сортировкой, надо сначала получить все(!) остальные строки. Иначе как тогда их упорядочить?! Поэтому "волшебные указатели" просто обязаны где-то быть! И они есть!!! В описании работы виртуального движка БД есть упоминание объекта Rowset, который может использоваться для сбора и сортировки (?) записей. Значит нам достаточно 1. ввести глобальные переменные Код: plaintext
2.создать свою экспортируемую функцию sqlite3_i_want_it_all[ (списываем ее с sqlite3step), которая дополнительно будет - устанавливать значение manushkin_solution в true, - вызывать sqlite3VdbeExec и - возвращать указатель на manushkin_array. 3. sqlite3VdbeExec подправим только слегка: - если manushkin_solution=true, то принудительно создаем объект rowset (в обычном случае он используется не всегда) и - в конце исполнения sqlite3VdbeExec (когда данные уже собраны, отсортированы и первая строка подготовлена к отправке в приложение) при manushkin_solution=true устанавливаем manushkin_array=@rowset, а rs (код результата исполнения sqlite3VdbeExec) = 666. - запрещаем дальнейшую работу с rowset, приостанавливаем виртуальный движок, чтобы он ненароком не освободил память, которая нам понадобится, не сбросил курсор и т.п. 4. Наша функция sqlite3_i_want_it_all, получив результат sqlite3VdbeExec=666, заканчивает выполнение возвращением приложению ссылки на manushkin_array, с которым мы работаем из delphi без дублирования данных. 5. Для работы с массивом (приведение его в читаемые данные) можно перевести на pascal функции, которые уже есть в sqlite.dll или экспортировать их. 6. После того, как мы сделали с данными все, что хотели, разрешаем окончание исполнения sqlite3VdbeExec, чтобы она освободила память и поудаляла все объекты, которые стали ненужны. И НИКАКОГО ДУБЛИРОВАНИЯ:) А еще можно сделать так, чтобы sqlite Использовала память, выделенную приложением (по-моему, в 3 версии это допускается) и, отслеживая ее состояние, получать данные напрямую в DrawGrid:) -- В общем, волшебные указатели иногда существуют, просто разработчик sqlite их тщательно скрыл, - SQLite, насколько я понимаю, именно поэтому и работает быстро. А твое приложение будет работать настолько быстро, насколько ты сам сумеешь его научить. Благодарю за рассмотрение данного вопроса. И все же сделал я через StringGrid, работает и как писали выше "горя не знает". Иногда мысли по оптимизации действительно мешают работе, а ведь хочется сделать идеально правильно. Спасибо всем. ... |
|||
:
Нравится:
Не нравится:
|
|||
18.01.2011, 20:00 |
|
|
start [/forum/topic.php?fid=54&msg=37061721&tid=2009242]: |
0ms |
get settings: |
10ms |
get forum list: |
13ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
74ms |
get topic data: |
11ms |
get forum data: |
3ms |
get page messages: |
48ms |
get tp. blocked users: |
1ms |
others: | 13ms |
total: | 181ms |
0 / 0 |