|
|
|
Два вопроса по оптимизации
|
|||
|---|---|---|---|
|
#18+
1. Если сервер стоит на XP на процессоре p4 с гипертредингом (northwood 3.2). Что указывать в MULTIPROCESSOR, NUMCPUVPS и SINGLE_CPU_VP ? С одной стороны - процессор все же один. С другой - вроде как и не один... 2. Есть вьюшка, одно из ее назначений - показывать только часть записей из таблицы - те, которые клиент имеет право видеть. Чтобы получить id и прочие атрибуты клиента я сделал несколько процедур, типа getmyuid() getmycategory() getmystatus() и т.д. - все, что они делают - выбирают какое-либо поле из таблицы клиентов глядя на user сессии. Посмотрел я на explain оптимизатора, который он выдает при выборке по подобной вьюшке - и ничего не понял. Я надеялся, что оптимизатор заставит сперва один раз отработать мои процедуры, и с их результатами сравнивать выбираемые строки пользуясь индексами, а получается, по-моему, что мои процедуры вызываются на каждую строку, естественно - никаких индексов?!! Более того, в зависимости от условий, одна и та же процедура фигурирует во вьюшке несколько раз, и, насколько я понял explain - informix так же тупо выполняет ее по нескольку раз на даже одну запись? не кэшируя результат?! Получается, проще выкинуть все эти процедуры, и увязывать вьюшку напрямую с таблицами в каждой вьюшке - тогда, по-идее, оптимизатор сперва повыберет всякие id-категории клиента и потом ужЕ с ними будет сверять строки выираемой таблицы? вот часть where из вьюшки: where c.id=h.clientid and ((h.clientid=GetMyCid() and GetMyUCategory()='A') or (c.parentid=GetMyCid() and (c.managerid=GetMyUid() or GetMyUCategory()='A'))); вот ее explain: QUERY: ------ select * from v_payhistory Estimated Cost: 3 Estimated # of Rows Returned: 1 1) informix.clients: SEQUENTIAL SCAN 2) informix.accpayhistory: INDEX PATH Filters: ((informix.accpayhistory.clientid = informix.getmycid()AND informix.getmyucategory()= 'A' ) OR (informix.clients.parentid = informix.getmycid()AND (informix.clients.managerid = informix.getmyuid()OR informix.getmyucategory()= 'A' ) ) ) (1) Index Keys: clientid (Serial, fragments: ALL) Lower Index Filter: informix.clients.id = informix.accpayhistory.clientid NESTED LOOP JOIN UDRs in query: -------------- UDR id : 858 UDR name: getmyucategory UDR id : 849 UDR name: getmyuid UDR id : 850 UDR name: getmycid UDR id : 858 UDR name: getmyucategory UDR id : 850 UDR name: getmycid ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.05.2005, 15:01 |
|
||
|
Два вопроса по оптимизации
|
|||
|---|---|---|---|
|
#18+
1. Если сервер стоит на XP на процессоре p4 с гипертредингом (northwood 3.2). Что указывать в MULTIPROCESSOR, NUMCPUVPS и SINGLE_CPU_VP ? С одной стороны - процессор все же один. С другой - вроде как и не один... Есть два принципиально разных варианта. 1. MULTIPROCESSOR 0 NUMCPUVPS 1 SINGLE_CPU_VP 1 2. MULTIPROCESSOR 1 NUMCPUVPS х SINGLE_CPU_VP 0 где x - от 2 до 4 (2*типа_CPU) Надо просто протестировать все четыре варианта на реальной нагрузке :) По вопросу 2. Да, обычно не надо заменять функциями JOIN, тем более, если соединяется не сотня таблиц - пусть оптимизатор работает... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.05.2005, 16:15 |
|
||
|
Два вопроса по оптимизации
|
|||
|---|---|---|---|
|
#18+
falcon111я сделал несколько процедур, типа getmyuid() getmycategory() getmystatus() и т.д. .............. так же тупо выполняет ее по нескольку раз на даже одну запись? не кэшируя результат?! Да, это штатное поведение. Если есть функция (к данному случаю сие не относится), значение которой зависит только от значения параметров и не зависит от содержимого таблиц базы, системного таймера и /dev/random, то в её описание надо добавить ключевое слово WITH NOT VARIANT. Тогда вычисляемое значение будет закешировано. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.05.2005, 17:50 |
|
||
|
Два вопроса по оптимизации
|
|||
|---|---|---|---|
|
#18+
falcon111...я сделал несколько процедур, типа getmyuid() getmycategory() getmystatus() и т.д. - все, что они делают - выбирают какое-либо поле из таблицы клиентов глядя на user сессии. Посмотрел я на explain оптимизатора, который он выдает при выборке по подобной вьюшке - и ничего не понял. Я надеялся, что оптимизатор заставит сперва один раз отработать мои процедуры, и с их результатами сравнивать выбираемые строки пользуясь индексами, а получается, по-моему, что мои процедуры вызываются на каждую строку, естественно - никаких индексов?!! Более того, в зависимости от условий, одна и та же процедура фигурирует во вьюшке несколько раз, и, насколько я понял explain - informix так же тупо выполняет ее по нескольку раз на даже одну запись? не кэшируя результат?! А как ты представляешь себе это - "кэшировать результат"? Можно кэшировать план выполнения запроса, но не значение поля таблицы, к которой имеют доступ еще многие приложения. Ведь сервер должен тебе гарантировать, что на момент обработки какой то 200-т тысячной строки через две минуты после начала обработки результат выполнения процедуры будет соответствовать реалиям настоящего момента, а не две минуты назад, ведь за эти две минуты в таблице могло ох как много измениться. "Многопользовательськая среда, сэр". Если тебе чихать на такие тонкости, то выполни процедуры один раз, запомни их результат в переменной или временной таблице и используй эти значения как фильтр. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.06.2005, 16:02 |
|
||
|
Два вопроса по оптимизации
|
|||
|---|---|---|---|
|
#18+
Ilya Kulagin falcon111я сделал несколько процедур, типа getmyuid() getmycategory() getmystatus() и т.д. .............. так же тупо выполняет ее по нескольку раз на даже одну запись? не кэшируя результат?! Да, это штатное поведение. Если есть функция (к данному случаю сие не относится), значение которой зависит только от значения параметров и не зависит от содержимого таблиц базы, системного таймера и /dev/random, то в её описание надо добавить ключевое слово WITH NOT VARIANT. Тогда вычисляемое значение будет закешировано. А можно с этого места подробнее? Я RTFM на этот предмет, и так понял, что это касается UDF, а не SPL. А почему я не хочу делать join, а использую процедуры: 1. Более читабельный SQL-вьюшки, кроме того, если что-то менять в системе доступа - нужно один раз поменять соответствующую процедуру, а не лопатить все вьюшки, в которых это проверяется. 2. Вьюшка получается update-бельная, т.е. на нее можно выполнять insert/update/delete. Если вместо процедур сделать join с таблицами юзеров и проверять доступы прямо в теле view, то такая вью становится read-only, как вью, затрагивающая другие таблицы, а меня это не устраивает. :( Есть ли какой-то способ по-человечески решить этот вопрос? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.06.2005, 17:42 |
|
||
|
Два вопроса по оптимизации
|
|||
|---|---|---|---|
|
#18+
2 vasilis: Кэширование значений может быть в том случае если у тебя при одних и тех же параметрах ф-ция выдает одно и тоже значение синус например. Значение синус от нуля сервер и кэширует. А если кто-то сказал серверу что функция значение которой зависит от кучи меняющихся данных возвращает одно и тоже значение сам себе злобный буратин :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.06.2005, 18:08 |
|
||
|
Два вопроса по оптимизации
|
|||
|---|---|---|---|
|
#18+
vasilisА как ты представляешь себе это - "кэшировать результат"? Можно кэшировать план выполнения запроса, но не значение поля таблицы, к которой имеют доступ еще многие приложения. Ведь сервер должен тебе гарантировать, что на момент обработки какой то 200-т тысячной строки через две минуты после начала обработки результат выполнения процедуры будет соответствовать реалиям настоящего момента, а не две минуты назад, ведь за эти две минуты в таблице могло ох как много измениться. "Многопользовательськая среда, сэр". Если тебе чихать на такие тонкости, то выполни процедуры один раз, запомни их результат в переменной или временной таблице и используй эти значения как фильтр. Примерно так: Если запрос выполняется в виде join с другой таблицей вместо процедуры, то оптимизатор выполняет запрос так - сперва выбирает id клиента по его сессии, затем этот ID сверяется с индексом выбираемой таблицы. Все быстро, все красиво. И я рассчитывал, что с процедурой будет что-то подобное, что нужно посмотреть на процедуру, что она не зависит ни от одной другой таблицы запроса, следовательно в запросе она - константа, нужно вычислить эту константу, и по ее результатам использовать нидекс. А если рассуждать так, что это типа многопользовательская среда, тогда индексы вообще использовать нельзя - ведь план выполнения строится так, что проверка доступа выбирается в начале, а потом по результату используется индекс большой таблицы. Кто-то точно так же может поменять таблицу юзеров, пока сервер выбирает записи из большой таблицы по индексу. Если рассуждать как ты, то индекс тоже нельзя использовать - нужно выбирать все записи, при этом постоянно проверяя таблицу юзеров. Как мне кажется, - это перебор. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.06.2005, 18:20 |
|
||
|
Два вопроса по оптимизации
|
|||
|---|---|---|---|
|
#18+
falcon111 Примерно так: Если запрос выполняется в виде join с другой таблицей вместо процедуры, то оптимизатор выполняет запрос так - сперва выбирает id клиента по его сессии, затем этот ID сверяется с индексом выбираемой таблицы. Все быстро, все красиво. И я рассчитывал, что с процедурой будет что-то подобное, что нужно посмотреть на процедуру, что она не зависит ни от одной другой таблицы запроса, следовательно в запросе она - константа, нужно вычислить эту константу, и по ее результатам использовать нидекс. Ну какая же она константа, если ЗАВИСИТ хоть от одной, но таблицы? Ну представь, что твой запрос идет 10минут и за это время из таблицы удалили запись со всеми параметрами твоего UserID. Процедура все еще будет возвращать данные, которых уже просто не существует в природе? Да и "посмотреть на процедуру" на предмет того, что она всегда вернет константу, довльно сложно - это такой анализатор надо строить, что мало не покажется... Но может я в чем то и неправ :) falcon111 А если рассуждать так, что это типа многопользовательская среда, тогда индексы вообще использовать нельзя - ведь план выполнения строится так, что проверка доступа выбирается в начале, а потом по результату используется индекс большой таблицы. Кто-то точно так же может поменять таблицу юзеров, пока сервер выбирает записи из большой таблицы по индексу. Если рассуждать как ты, то индекс тоже нельзя использовать - нужно выбирать все записи, при этом постоянно проверяя таблицу юзеров. Как мне кажется, - это перебор. Так ведь проверяется :) Посмотри Гуглем в конференции ukr.comp.dbms.informix топик "О скорости" за июль 2003 года - там описан интересный эксперимент, в котором видно сколько раз читается таблица sysusers (да еще и блокировки устанавливаются :) при работе рядового пользователя. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.06.2005, 22:48 |
|
||
|
Два вопроса по оптимизации
|
|||
|---|---|---|---|
|
#18+
falcon111 А почему я не хочу делать join, а использую процедуры: 1. Более читабельный SQL-вьюшки, кроме того, если что-то менять в системе доступа - нужно один раз поменять соответствующую процедуру, а не лопатить все вьюшки, в которых это проверяется. Когда мне понадобилось ограничить доступ к информации по транзакциям (Все транзакции хранятся в одной таблице. Однако, клиенту можно показывать только его транзакции. Точнее, транзакции по его счёту. Дополнительно бывает нужно ограничить его также некоторыми типами транзакций. Ну и ещё по ходу дела всякие условия придумываются), то самым простым способом оказалось написание процедуры, возвращающей готовый результат. Вариантов возврата результата два: - непосредственно из процедуры, при этом данные не именованы и у некоторых средств разработки едет крыша - во временной таблице, возможно, создаваемой самой процедурой. Тут надо предусмотреть возможность одновременного нескольких запросов внутри одной сессии. По крайней мере, для веб-интерфейса это крайне актуально. Во-вторых, данных может оказаться изрядно много. Вот такой был опыт. Кстати, разрешения на select по таблицам при предоставлении данных посредством sp пользователю базы можно не давать. И даже connect можно не давать, если процедуры в отдельной database хранить. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.06.2005, 16:33 |
|
||
|
Два вопроса по оптимизации
|
|||
|---|---|---|---|
|
#18+
falcon111 А почему я не хочу делать join, а использую процедуры: 1. Более читабельный SQL-вьюшки, кроме того, если что-то менять в системе доступа - нужно один раз поменять соответствующую процедуру, а не лопатить все вьюшки, в которых это проверяется. 2. Вьюшка получается update-бельная, т.е. на нее можно выполнять insert/update/delete. Если вместо процедур сделать join с таблицами юзеров и проверять доступы прямо в теле view, то такая вью становится read-only, как вью, затрагивающая другие таблицы, а меня это не устраивает. :( Есть ли какой-то способ по-человечески решить этот вопрос? Я тоже свое время страдал этой фигней, и пришел к выводу, что использование такого вида: CREATE VIEW v_bonus AS SELECT * FROM bonus WHERE div_status in (SELECT * FROM TABLE(get_dependent_id())); работает гораздо быстрее, чем просто div_status=get_dependent_id() Однако, увлекаться не стоит, ибо одна из разновидностей такого запроса просто роняет сервер (бага висит в IBM'е, говорят на 9.40UC6 тоже роняет) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.06.2005, 09:33 |
|
||
|
|

start [/forum/topic.php?fid=44&msg=33103352&tid=1609011]: |
0ms |
get settings: |
8ms |
get forum list: |
10ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
40ms |
get topic data: |
8ms |
get forum data: |
2ms |
get page messages: |
39ms |
get tp. blocked users: |
1ms |
| others: | 228ms |
| total: | 340ms |

| 0 / 0 |
