[ОТВЕТИТЬ]
26.06.2008 14:33
Mihon
 
Написал запросик (кстати, разместил его в FAQ по СМ), однако слишком мало тестил (тесты на базах магазинов).
Тестил на базе давностью ~1 месяц - запрос работает ~4 минут, и все возвращает, как положено.
Тестил на базе давностью 1,5 года - вот тут уже сложности начались - сначало на тэйблспейс temp обругалось, потом на сегменты RBS. RBS увеличили, не помогло.
Собственно, вопрос:
Как выбрать оптимальное кол-во сегментов, их размер и размер тэйблспэйсов?
Не будет ли так, что запросик мой СЛИШКОМ громоздкий, и всех этих рбс-ов для него надо очень жирных и много. Если их сделать слишком много и слишком больших, не отразится ли это плохо на базе и на быстродействии?
размер базы - 11,5 гб
Oracle 8i
Сегментов RBS 24 шт. по 10 мб (optimal size) 4 мб (next size).
Тэйблспэйс RBS один на 2 гига
текст запроса:
Код:
SELECT 
  to_char(cc.printtime,'DD.MM.YYYY') "date", sp.article, sp.docid, 
max(
(to_number(to_char(cc.printtime,'hh24'))*60 +
 to_number(to_char(cc.printtime,'mi'))) -
(to_number(to_char(log.eventtime,'hh24'))*60 +
 to_number(to_char(log.eventtime,'mi')))
) "minutes", 
to_char(log.eventtime,'hh24:mi:ss') "change_price_time", to_char(cc.printtime,'hh24:mi:ss') "check_time", sp.itemprice "Price", cci.itemprice "check_price"

FROM 
  SUPERMAG.Smspec sp,
  SUPERMAG.Smdoclog log,
  SUPERMAG.Smcashchecks cc,
  SUPERMAG.Smcashcheckitems cci
where 
  log.doctype='AC' and
  log.oldstate=2 and
  log.newstate=3 and
  log.id=sp.docid and
  sp.article=cci.article and
  cc.desknum=cci.desknum and
  cc.znum=cci.znum and
  cc.checknum=cci.checknum and
  to_char(cc.printtime,'DD.MM.YYYY') =to_char(log.eventtime,'DD.MM.YYYY') and
  cci.itemprice<>sp.itemprice and
  cc.printtime-log.eventtime>0

group by 
sp.article, sp.docid, log.eventtime, cc.printtime, cci.itemprice, sp.itemprice
еще добавлял в where log.eventtime>='01.04.2008' - все равно обругалось.
а вот с '01.06.2008' получилось, хотя и ждал минут 20...
26.06.2008 15:31
Mtirt
 
Вот это явно заведомо долго будет выполняться:
to_char(cc.printtime,'DD.MM.YYYY') =to_char(log.eventtime,'DD.MM.YYYY')
and cc.printtime-log.eventtime>0
26.06.2008 16:46
Mihon
 
Цитата:
Mtirt Вот это явно заведомо долго будет выполняться:
to_char(cc.printtime,'DD.MM.YYYY') =to_char(log.eventtime,'DD.MM.YYYY')
and cc.printtime-log.eventtime>0
а чем можно заменить, что попроще?
26.06.2008 17:23
Mtirt
 
В твоем случае - скорее всего ничем.
26.06.2008 17:24
akonev
 
(cc.printtime - log.eventtime) < 1 and
cc.printtime>log.eventtime
26.06.2008 17:32
Mtirt
 
Тут суть в том, что и в той и в другой таблице это неиндексируемое поле.
А обе таблички совсем немаленькие.
Как следствие - прямое чтение с диска больших объемов данных.
План запроса (последние три графы cost, cardinality, byte):
Код:
SELECT STATEMENT, GOAL = CHOOSE            297444    109    9047
 SORT GROUP BY            297444    109    9047
  HASH JOIN            297443    109    9047
   TABLE ACCESS FULL    SUPERMAG    SMCASHCHECKS    36    32645    489675
   HASH JOIN            297397    218582    14863576
    TABLE ACCESS FULL    SUPERMAG    SMCASHCHECKITEMS    41    32645    587610
    HASH JOIN            297321    884376    44218800
     TABLE ACCESS FULL    SUPERMAG    SMDOCLOG    27824    20131    523406
     TABLE ACCESS FULL    SUPERMAG    SMSPEC    262797    178869173    4292860152
26.06.2008 17:42
Mtirt
 
Цитата:
Andrew_Konev (cc.printtime - log.eventtime) < 1 and
cc.printtime>log.eventtime
Судя по плану запроса на порядок лучше :)
Код:
 SELECT STATEMENT, GOAL = CHOOSE            27931    1    83
 SORT GROUP BY            27931    1    83
  TABLE ACCESS BY INDEX ROWID    SUPERMAG    SMSPEC    14    1    24
   NESTED LOOPS            27930    1    83
    HASH JOIN            27917    1    59
     MERGE JOIN            27874    1    41
      SORT JOIN            27830    20131    523406
       TABLE ACCESS FULL    SUPERMAG    SMDOCLOG    27824    20131    523406
      FILTER                    
       SORT JOIN                    
        TABLE ACCESS FULL    SUPERMAG    SMCASHCHECKS    36    32645    489675
     TABLE ACCESS FULL    SUPERMAG    SMCASHCHECKITEMS    41    32645    587610
    INDEX RANGE SCAN    SUPERMAG    SMSPEC_ART    13    1
27.06.2008 16:43
Mihon
 
а что по поводу рбс-ов?
27.06.2008 16:47
Mtirt
 
Если ты будешь запросом меньше грузить базу, тебе RBS настраивать не придется.
27.06.2008 16:56
Mihon
 
Это я понял. А как можно оптимизировать запрос?
27.06.2008 16:59
Mtirt
 
Например, как предложил Андрей. Судя по плану запроса, выложенному мной, там всё стало намного лучше...
27.06.2008 17:07
Mihon
 
Ок, спасибо, попробую.

эээээ
Код:
(to_number(to_char(cc.printtime,'hh24'))*60 +
 to_number(to_char(cc.printtime,'mi'))) -
(to_number(to_char(log.eventtime,'hh24'))*60 +
 to_number(to_char(log.eventtime,'mi'))) >0
а так не прокатит?
27.06.2008 17:12
Mtirt
 
Нет. Не прокатит:
Цитата:
SELECT STATEMENT, GOAL = CHOOSE 297627 10929 907107
SORT GROUP BY 297627 10929 907107
HASH JOIN 297443 10929 907107
TABLE ACCESS FULL SUPERMAG SMCASHCHECKS 36 32645 489675
HASH JOIN 297397 218582 14863576
TABLE ACCESS FULL SUPERMAG SMCASHCHECKITEMS 41 32645 587610
HASH JOIN 297321 884376 44218800
TABLE ACCESS FULL SUPERMAG SMDOCLOG 27824 20131 523406
TABLE ACCESS FULL SUPERMAG SMSPEC 262797 178869173 4292860152
28.06.2008 06:46
akonev
 
Вот только у моего варианта смысл немного другой.
У тебя было: продажи после переоценки в тот же день.
У меня: продажи после переоценки в течение суток.

Но зато убираются лишние преобразования типов над каждой записью по полям, участвующим в условиях.

можно еще этот кусок попробовать переделать
Код:
max(
(to_number(to_char(cc.printtime,'hh24')) * 60 +
 to_number(to_char(cc.printtime,'mi'))) -
(to_number(to_char(log.eventtime,'hh24')) * 60 +
 to_number(to_char(log.eventtime,'mi')))
) "minutes"
примерно так
Код:
((max(cc.printtime - log.eventtime)) * 1440) "minutes"
только результат округлить еще надо для читабельности.
30.06.2008 10:54
Mihon
 
Сделал так, как посоветовали. Мой запрос выполняется порядка пяти минут на небольшой базе за месяц. Переделанный запрос - висел минут 30 и вывалился с ошибкой РБС. Так и должно быть?
30.06.2008 10:55
Mihon
 
вот текст измененного запроса. так должно быть?
Код:
SELECT 
  to_char(cc.printtime,'DD.MM.YYYY') "date", sp.article, sp.docid, 
((max(cc.printtime - log.eventtime)) * 1440) "minutes", 
to_char(log.eventtime,'hh24:mi:ss') "change_price_time", to_char(cc.printtime,'hh24:mi:ss') "check_time", sp.itemprice "Price", cci.itemprice "check_price"

FROM 
  SUPERMAG.Smspec sp,
  SUPERMAG.Smdoclog log,
  SUPERMAG.Smcashchecks cc,
  SUPERMAG.Smcashcheckitems cci
where 
  log.doctype='AC' and
  log.oldstate=2 and
  log.newstate=3 and
  log.id=sp.docid and
  sp.article=cci.article and
  cc.desknum=cci.desknum and
  cc.znum=cci.znum and
  cc.checknum=cci.checknum and
  to_char(cc.printtime,'DD.MM.YYYY') =to_char(log.eventtime,'DD.MM.YYYY') and
  cci.itemprice<>sp.itemprice and
  (cc.printtime - log.eventtime) < 1 and
  cc.printtime>log.eventtime

group by 
sp.article, sp.docid, log.eventtime, cc.printtime, cci.itemprice, sp.itemprice
30.06.2008 10:57
Mtirt
 
Вот это убери
Код:
 to_char(cc.printtime,'DD.MM.YYYY') =to_char(log.eventtime,'DD.MM.YYYY') and
30.06.2008 10:59
Mtirt
 
Кстати, в принципе можно вообще оставить только:
Код:
(cc.printtime - log.eventtime) > 0
30.06.2008 15:13
akonev
 
Цитата:
Mtirt Кстати, в принципе можно вообще оставить только:
Код:
(cc.printtime - log.eventtime) > 0
Это, наверное, нехорошо будет. полезут же все чеки, более поздние, чем переоценка.
если переоценка была год назад - совсем беда.
надо тогда еще максимальный cc.printtime задавать и минимальный log.eventtime (его, кстати, надо в любом случае. ну кому нафиг нужны эти задержки прохода цены на кассу годичной давности?)
30.06.2008 15:30
akonev
 
у меня вообще начало складываться устойчивое подозрение, что для гарантированной работоспособности надо все это безобразие оформлять как pl/sql-процедуру.

в ней отбирать во временную таблицу max(сc.printtime) для каждой переоценки в отдельности. и с коммитом после каждого документа.

быстрее может и не станет (хотя станет, скорее всего), но зато время выполнения будет почти линейно зависеть от количества переоценок.

станет проще оценивать время работы и подбирать параметры периода документов и периода чеков.
да и от проблем с рбс, наверняка, избавимся, за счет частых коммитов.

а потом уже отдельным запросом форматировать вывод из этой таблицы для читания человеками.
30.06.2008 15:51
Mtirt
 
Ага. чеки можно отобрать по времени и по артикулам, которые есть в актах переоценки, и это будет быстрее, чем лопатить всю кучу целиком...
Опции темы


Часовой пояс GMT +3, время: 20:08.

 

Форум сделан на основе vBulletin®
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd. Перевод: zCarot и OlegON
В случае заимствования информации гипертекстовая индексируемая ссылка на Форум обязательна.