Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet / 25 сообщений из 46, страница 1 из 2
26.07.2014, 11:40
    #38706493
Таблоид
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
"И снова здравствуйте!".

При очередном перечитывании Писания : 1.2.3. Навигация по индексу

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

Почему нельзя сначала пройтись по всем ключикам (с учётом where / rows ограничений, если они есть) и затолкать ID'шники записей в структуру типа TreeSet, которую по окончании сканирования индеска можно спокойно юзать для обхода записей в порядке возрастания их ID - ?
Да, понятно, что такой селект не выдаст клиенту ни одной строки до тех пор, пока не доберётся до последнего ключа и не начнёт выдавать содержимое TreeSet'a. Но селект ведь не только для выдачи результата клиенту юзается, а еще и просто для обработки строк в нужном порядке (т.е. курсором: for select ... from <T> where ... ORDER BY <F1, F2> as cursor C do ...)
...
Рейтинг: 0 / 0
26.07.2014, 12:05
    #38706496
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
ТаблоидПочему нельзя сначала пройтись по всем ключикам (с учётом where / rows ограничений, если они есть) и затолкать ID'шники записей в структуру типа TreeSet, которую по окончании сканирования индеска можно спокойно юзать для обхода записей в порядке возрастания их ID - ?

лучше ответь зачем это нужно
...
Рейтинг: 0 / 0
26.07.2014, 12:52
    #38706510
Таблоид
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
Что "зачем" ? Уменьшение числа random IO ?
...
Рейтинг: 0 / 0
26.07.2014, 12:57
    #38706513
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
Таблоид,

кхе... порядок IDшников записей далеко не всегда (читай почти никогда, если это не ПК) совпадает с порядком ключей сортировки
...
Рейтинг: 0 / 0
26.07.2014, 12:59
    #38706514
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
Симонов Денис,

даже ПК это не гарантирует. А кластерных индексов (Index Organized Table) в FB нету
...
Рейтинг: 0 / 0
26.07.2014, 13:17
    #38706521
Таблоид
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
Симонов Денискхе... порядок IDшников записей далеко не всегда (читай почти никогда, если это не ПК) совпадает с порядком ключей сортировкиНу так я про то и говорю! Раз он не совпадает, значит, надо сначала пройтись по индексу и каждый ID записи, который там будет встречен, помещать предварительно в TreeSet. И только после окончания навигации начинать выталкивать из TreeSet'a его содержимое.

Допустим, в индексе на страницах 123 и 124 сидят следующие ключи с ID'шниками:
index page =>123123123123124124124124index keys =>abcabcdbcdebcdefbcdfabcdfbbczbcz2rec IDs =>65432112345678901265002112159014999991112

Навигация начинается с левого ключа, т.е. с 'abc'. Там ID'шник = 654321 - помещаем его в TreeSet, но НЕ выдаём ничего пока что клиенту.
Далее переходим к ключу 'abcd', там ID'шник = 123456. Добавляем его в TreeSet, содержимое этого дерева будет теперь таким, что его итерация по его элементам выдаст (автоматом) их так: 123456, 654321.
Затем переходим дальше, к ключу 'bcde', там ID = 789012, и т.д.

В результате, по окончании этого процесса TreeSet будет таким, что итератор по нему выдаст элементы (ID'шники записей) в порядке их возрастания:
TreeSet iter.next()21212345615901465002165432178901299999111
И вот только тут, на этапе итерации по этому дереву, начинаем проверять видимость записей нашей транзакции и выдаём их на гор а , если сиё допускается. И обходим эти записи уже в порядке возрастания ID'шников.
...
Рейтинг: 0 / 0
26.07.2014, 13:34
    #38706526
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
Таблоид,

ну так порядок то будет не тот. Мы хотели вернуть записи в порядке ключей индексы, а после твоего алгоритма они нам вернутся в порядке расположения на диске.
...
Рейтинг: 0 / 0
26.07.2014, 13:36
    #38706527
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
ТаблоидИ обходим эти записи уже в порядке возрастания ID'шников
И в какое место эти записи засунет пользователь, если он их просил совсем в другом порядке?..

То, о чём ты говоришь, это есть план INDEX. Который от ORDER несколько отличается.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
26.07.2014, 13:36
    #38706528
Таблоид
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
Симонов Денисну так порядок то будет не тот. а, тьфу... точно :-)
ну ладно, значит не судьба...
...
Рейтинг: 0 / 0
26.07.2014, 13:38
    #38706530
Таблоид
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
я в печальке большой: не могу в одном месте избавиться от этого PLAN ORDER'a, бызнес-логика его требует.
И именно из-за него получаю совершенно дикие значения по произв-сти в трейсе.
...
Рейтинг: 0 / 0
26.07.2014, 13:44
    #38706531
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
ТаблоидИ именно из-за него получаю совершенно дикие значения по произв-сти в
трейсе.
Кэш увеличь, чтобы нужный индекс в него помещался.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
26.07.2014, 13:57
    #38706536
Таблоид
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
Dimitry SibiryakovТаблоидИ именно из-за него получаю совершенно дикие значения по произв-сти в трейсе.Кэш увеличь, чтобы нужный индекс в него помещался.
Кеш в SS поставил давно уже 512К, в трейсе при таком значении практически никогда не лезут read(s)>0.
А в SC пробовал и с кешем 16384 (больше не задавал, вряд ли такое увидишь в реале :)), но read(s)>0 периодически прут.
И сильно подозреваю, что даже если выставить в SC еще бОльший кеш ради истребления reads'ов - не поможет. Ибо SS тому пример.
...
Рейтинг: 0 / 0
26.07.2014, 14:19
    #38706546
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
Таблоидне могу в одном месте избавиться от этого PLAN ORDER'a, бызнес-логика его требует.

бизнес логика не может требовать какого то плана. Сортировки может, но не плана. Если это связано с твоим тестом OLTP скажи в каком месте, может идеи какие придут.
...
Рейтинг: 0 / 0
26.07.2014, 14:23
    #38706549
kdv
kdv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
Таблоидне могу в одном месте избавиться от этого PLAN ORDER'a
насколько я в курсе, всегда можно избавиться от PLAN ORDER, только он поменяется на PLAN SORT. если при ORDER дофига random io, то SORT будет хорошо.
...
Рейтинг: 0 / 0
26.07.2014, 17:14
    #38706595
Таблоид
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
Симонов Денис,

там есть две процедурки, отвечающие за сторнирование количеств и стоимостей: sp_make_qty_storno & sp_make_cost_storno.
У них (в твоей версии теста) курсоры, обрабатывающие строки, делают это с PLAN ORDER. Сколько я не крутил-мутил с индексами, ничего там не улучшилось.
Курсорный запрос вида:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
            select
                 q.rdb$db_key as dbkey
                ,q.id
                ,q.doc_id as snd_list_id
                ,q.snd_id as snd_data_id
                ,q.snd_qty
                ,q.snd_purchase
                ,q.snd_retail
                ,q.snd_optype_id
                ,q.rcv_optype_id
            from qdistr q
            where
                  q.snd_optype_id = :snd_optype_id
                  and q.rcv_optype_id  = :rcv_optype_id
                  and q.ware_id = :ware_id
            order by q.doc_id, q.snd_id
            as cursor cq

- вгонял всё в гроб.
После добавления волшебного "плюс-нолика" в его order by всё залетало, ускорение в десятки раз.
Но это и другие исправления я еще тебе не высылал.

Однако, остались еще режимы, где PLAN ORDER таки требуется. Это выбор случайных документов для обработки - то, что делает fn_get_random_id через вот то: select id from <view_for_random_search> where id >= :x ORDER BY ID rows 1.
Почесав репу, я догадался, что вряде случаев можно и здесь убрать ORDER BY, потому что как только документ успешно залочен и взят в обработку, то при успешном её завершении он - возможно - исчезнет из видимости вьюхи <view_for_random_search>, т.к. перейдёт в такое состояние, когда по нему "всё сторнировано".
Но это будет НЕ СРАЗУ, а при многократных обработках выбранного док-та, т.к. за один присест с него сдёргивается для сторнирования не всё кол-во. Поэтому мне совсем не нравится этот подход, ибо костыль же, явный и убогий.
...
Рейтинг: 0 / 0
26.07.2014, 17:15
    #38706596
Таблоид
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
kdvТаблоидне могу в одном месте избавиться от этого PLAN ORDER'aнасколько я в курсе, всегда можно избавиться от PLAN ORDER, только он поменяется на PLAN SORT. если при ORDER дофига random io, то SORT будет хорошо.Можно, ес-сно. Но только если объем записей для SORT'a не очень большой. Именно так у мну, к щясью, и происходит.
...
Рейтинг: 0 / 0
26.07.2014, 17:27
    #38706599
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
Таблоид,

как раз когда есть ограничитель rows, да ещё и стоит там всего одна запись, PLAN ORDER будет эффективней чем SORT. Для трёшки вроде обещали сделать оптимизацию по-умолчанию для случая когда выбираются все записи. Сейчас это заметно когда есть JOIN. Оптимизатор меняет порядок соединения, если есть ограничитель ROWS.

Код: sql
1.
2.
3.
4.
5.
select horse.name,
       color.name
from horse
join color on horse.code_color = color.code_color
order by horse.name



PLAN SORT (JOIN (COLOR NATURAL, HORSE INDEX (FK_HORSE_COLOR)))

Код: sql
1.
2.
3.
4.
5.
select horse.name,
       color.name
from horse
join color on horse.code_color = color.code_color
order by horse.name rows 1



PLAN JOIN (HORSE ORDER HORSE_IDX_NAME, COLOR INDEX (PK_COLOR))

Правда сейчас абсолютно пофиг сколько я там укажу в rows хоть 10e9 план будет выбран второй.

Может тебе сей пример чем и поможет
...
Рейтинг: 0 / 0
26.07.2014, 17:35
    #38706603
Таблоид
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
Таблоидну ладно, значит не судьба...А нет, стоп. Всё таки - судьба! :-)
Формируем битмап для хранения ID'шников, а также Tree Map , в котором:
<Key> - это результат вычисления для каждой записи выражения ORDER BY (т.е. значений одного или нескольких полей);
<Val> - это все прочие поля, не указанные в ORDER BY (кроме блобов, ес-сно; для них туда пишем только указатели).

Стартуем так, как делается при PLAN INDEX, в итоге будет сформирован битмап.
Далее, по нему делаем обход записей в порядке возрастания ID'шников, вытаскивая из записей все поля, которые были перечислены в ORDER BY и в SELECT-секции.

Для каждой такой записи проверяем её видимость текущей транзакции и если Ок, то заполняем <key> & <val> нашего TreeMap'a.

А затем - вываливаем вызывателю содержимое TreeMap'a, вызывая его итератор.

В итоге получаем:
1) однократное посещение записей и только в порядке возрастания их ID;
2) вывод из TreeMap'a идёт в том порядке, что задан был в ORDER BY.

Минус вижу только один: доп. расход памяти. Но в наш суровый век дешёвых терабайтов это не должно быть существенным.
...
Рейтинг: 0 / 0
26.07.2014, 17:42
    #38706605
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
Таблоид,

и чем это лучше чем сортировка в памяти (не навигация по индексу)
...
Рейтинг: 0 / 0
26.07.2014, 17:44
    #38706606
Таблоид
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
Симонов Денискак раз когда есть ограничитель rows, да ещё и стоит там всего одна запись, PLAN ORDER будет эффективней чем SORT. Я не увидел этой эффективности, когда база под нагрузкой.
Именно на запросах вида select ID from <view> where ID >= :x ORDER BY ID rows 1 неоднократно получал в трейсе то 5, а то 10 сек. И это при том, что ORDER BY - по первичному ключу, т.е. у нас достаточно большая вероятность того, что физ. порядок следования записей соотв-вует индексному.
...
Рейтинг: 0 / 0
26.07.2014, 17:45
    #38706607
Таблоид
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
Симонов Дениси чем это лучше чем сортировка в памяти (не навигация по индексу)Хм... не знаю, сравнивать надо. Но один плюсик всё же есть: не нужно будет костыли всовывать везде (я про "+0").
...
Рейтинг: 0 / 0
26.07.2014, 17:55
    #38706609
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
Таблоид,

значит у тебя вьюха хитрая. На простой таблице выигрыш просто огромный

Код: sql
1.
2.
3.
4.
select code_horse
from horse
where code_horse >= 1100000
order by horse.code_horse rows 1



Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
План
PLAN (HORSE ORDER PK_HORSE)

------ Информация о производительности ------
Время подготовки запроса = 0ms
Время выполнения запроса = 16ms
Среднее время на получение одной записи = 16,00 ms
Current memory = 279 747 240
Max memory = 279 823 208
Memory buffers = 16 384
Reads from disk to cache = 0
Writes from cache to disk = 0
Чтений из кэша = 8

Код: sql
1.
2.
3.
4.
select code_horse
from horse
where code_horse >= 1100000
order by horse.code_horse+0 rows 1



Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
План
PLAN SORT (HORSE INDEX (PK_HORSE))

------ Информация о производительности ------
Время подготовки запроса = 0ms
Время выполнения запроса = 63ms
Среднее время на получение одной записи = 63,00 ms
Current memory = 279 793 464
Max memory = 281 892 944
Memory buffers = 16 384
Reads from disk to cache = 0
Writes from cache to disk = 0
Чтений из кэша = 54 861
...
Рейтинг: 0 / 0
26.07.2014, 18:39
    #38706619
Таблоид
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
Симонов Денисзначит у тебя вьюха хитрая. Не, примитивизм сплошной:
Код: sql
1.
2.
3.
4.
5.
6.
create or alter view v_cancel_customer_reserve as
select h.id
from doc_list h
where
    h.optype_id = fn_oper_retail_reserve()
;

Где fn_oper_retail_reserve() - детерминистик-функция, лезет в базу только при первом своём вызове. При последующих возвращает ID операции, сохранённый у себя в кошельке. И даже если заменить её на тупой литерал (у мну - 3000), не поможет, не в ней дело.

Симонов ДенисНа простой таблице выигрыш просто огромныйКак-то не очень сильно бросилось в глаза... 16 мс против 63 ? это ты ведь в моно-коннекте сделал, так ?
...
Рейтинг: 0 / 0
26.07.2014, 18:53
    #38706621
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
ТаблоидКак-то не очень сильно бросилось в глаза... 16 мс против 63 ? это ты ведь в моно-коннекте сделал, так ?

это второй раз когда всё уже в кеш всосалось. Посмотри на количество фетчей.

Когда указана инструкция rows 1, то огромного random IO быть не должно, так как после первого фетча всё прекратится. Разве что приходится целиком прочитать индекс и то в твоём случае должен быть Range Scan

Код: sql
1.
2.
3.
4.
select h.id
from doc_list h
where
    h.optype_id = fn_oper_retail_reserve() -- это может помешать



тут скорее всего для optype_id есть дополнительный индекс
вот тебе для сравнения

Код: sql
1.
2.
3.
4.
5.
select code_horse
from horse
where code_horse >= 1100000 and
      code_breed = 65
order by horse.code_horse rows 1



Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
План
PLAN (HORSE ORDER PK_HORSE INDEX (FK_HORSE_BREED))

------ Информация о производительности ------
Время подготовки запроса = 0ms
Время выполнения запроса = 15ms
Среднее время на получение одной записи = 15,00 ms
Current memory = 279 843 232
Max memory = 281 658 848
Memory buffers = 16 384
Reads from disk to cache = 0
Writes from cache to disk = 0
Чтений из кэша = 34

Чтений из кэша стало больше 34 vs 8
...
Рейтинг: 0 / 0
26.07.2014, 20:32
    #38706634
Таблоид
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet
Симонов Денистут скорее всего для optype_id есть дополнительный индекс есть, конечно же (см DDL, их есть у тебя).
Только вот какое дело: не вижу я чё-то при работе в моноконнекте никаких осязаемых преимуществ order by id+0 над order by id.

Вот пример.
DDL:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
-- create sequence g;
alter sequence g restart with 0; commit;
recreate table t(id int, x int); commit;
recreate global temporary table gtt(id int, r int) on commit delete rows; commit;
create index gtt_r on gtt(r); commit;

set term ^;
execute block as
declare variable n int = 500000;
begin
  while (n>0) do insert into gtt(id, r) values( gen_id(g,1), rand()*1000000 ) returning :n-1 into n;
end
^set term ;^
insert into t(id,x) select id, rand()*9999 from gtt order by r;
commit;

create index t_id on t(id);
create index t_x on t(x);
commit;

recreate table t_log(trn_id int default current_transaction primary key, done_searchs int, avg_ms_for_one_search int);
commit;

drop table gtt;
commit;
(будет создана таблица t(id, x) с 500 тыс записями, но физ. расположение строк в ней будет отвратительным с т.зр. навигации по ID-индексу.

Test:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
execute block
as
  declare n int = 1000;
  declare i int;
  declare v_min_x int;
  declare v_max_x int;
  declare v_min_id double precision;
  declare v_max_id double precision;
  declare v_cur_id double precision;
  declare v_stt varchar(80);
  declare t0 timestamp;
  declare x int;
  declare c smallint = 1;
begin
   select min(id)-0.5 from t into v_min_id;
   select max(id)+0.5 from t into v_max_id;
   select min(x) from t into v_min_x;
   select max(x) from t into v_max_x;
   x=v_min_x + rand()*( v_max_x - v_min_x );
   if (c = 1) then
     v_stt = 'select id from t where x = :x and id >= :y ORDER BY id rows 1';
   else
     v_stt = 'select id from t where x = :x and id >= :y ORDER BY id+0 rows 1';

   t0='now';
   i=n;
   while (i > 0) do
   begin
      execute statement (v_stt) ( x := :x, y := v_min_id + rand()*( v_max_id - v_min_id ) ) into v_cur_id;
      i = i-1;
   end
   update or insert into t_log(trn_id, done_searchs, avg_ms_for_one_search)
   values( current_transaction, :n, datediff(millisecond from :t0 to cast('now' as timestamp)) / :n );

end



Запусти у себя сначала с "declare c smallint = 1;", а затем поменяй на "declare c smallint = 2;", чтобы вызовы были с order by id+0.
Я разницу как-то не ощутил.

Может, в сильно-конкурентной среде, когда в таблицу `t` будут падать новые строки, будет всё по-другому, не знаю.
...
Рейтинг: 0 / 0
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / PLAN ORDER (навигация по индексу) и сохранение считанных recId в аналоге TreeSet / 25 сообщений из 46, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]