SlideShare ist ein Scribd-Unternehmen logo
1 von 44
Downloaden Sie, um offline zu lesen
Olivier Dony
T @odony
Performance
with high
volumes
OpenERP can handle large
volumes of transactions and
large volumes of data
out of the box!
For example, each OpenERP
Online Server hosts 1000+
databases without
breaking a sweat!
Many on-site customers have
single server deployments
with millions of rows:
partners, emails, attachments,
journal items, stock moves,
workflow items, …
What if performance is an issue?
Get the right facts.
Use the right tools.
t @odony
Agenda
● Architecture / Deployment / Sizing
● Measuring & Analyzing
● Common Problems
● Anti-patterns
t @odony
OpenERP Architecture
PostgreSQL is the real
workhorse behind OpenERP,
and it scales very well!
t @odony
OpenERP Cron Worker
Deployment Architecture: single server, multi-process
Rule of thumb:
--workers=$((1+${CORES}*2))
OpenERP HTTP Worker
OpenERP HTTP Worker
OpenERP HTTP Worker
OpenERP HTTP Worker
PostgreSQL
Requests
t @odony
OpenERP Cron Worker
Deployment Architecture: multi-server, multi-process
OpenERP HTTP Worker
OpenERP HTTP Worker
OpenERP HTTP Worker
OpenERP HTTP Worker
PostgreSQL
Requests
Server 3
Load
Balancer
OpenERP Cron Worker
OpenERP HTTP Worker
OpenERP HTTP Worker
OpenERP HTTP Worker
OpenERP HTTP Worker
Server 2
Server 1
t @odony
Hardware Sizing
● Typical modern server machine
● 4/8/12 2+GHz cores
● 8-64 GB RAM
● Fast SATA/SAS/SSD disks
● Up to 100-200 active users (multi-process)
● Up to dozens of HTTP requests per second
● Up to 1000 β€œlight” users (average SaaS user)
● For official OpenERP 7.0 deployments with no
customizations, and typical usage!
For anything else, always
perform proper load testing
before going live in production!
Then size accordingly...
t @odony
PostgreSQL Deployment tips
● Avoid deploying PostgreSQL on a VM
● If you must do it, fine-tune the VM for I/O!
● And always check out the basic PostgreSQL
performance tuning, it's conservative by
default
http://wiki.postgresql.org/wiki/Tuning_Your_PostgreSQL_Server
t @odony
Agenda
● Architecture / Deployment / Sizing
● Measuring & Analyzing
● Common Problems
● Anti-patterns
t @odony
Monitor application response times
●
You can't manage/improve what you can't
measure
●
Setup an automated monitoring of performance
and response time... even if you have no
performance problem!
●
Suggested tool: munin
●
Run OpenERP with –log-level=debug_rpc in prod!
2013-07-03 00:12:29,846 9663 DEBUG test openerp.netsvc.rpc.request:
object.execute_kw time:0.031s mem: 763716k -> 763716k (diff: 0k)('test', 1,
'*', 'sale.order', 'read', (...), {...})
t @odony
#!/bin/sh
#%# family=manual
#%# capabilities=autoconf suggest
case $1 in
autoconf)
exit 0
;;
suggest)
exit 0
;;
config)
echo graph_category openerp
echo graph_title openerp rpc request count
echo graph_vlabel num requests/minute in last 5 minutes
echo requests.label num requests
exit 0
;;
esac
# watch out for the time zone of the logs => using date -u for UTC timestamps
result=$(tail -60000 /var/log/openerp.log | grep "object.execute_kw time" | awk "BEGIN{count=0} ($1 " " 
$2) >= "`date +'%F %H:%M:%S' -ud '5 min ago'`" { count+=1; } END{print count/5}")
echo "requests.value ${result}"
exit 0
Munin plugin: OpenERP requests/minute
t @odony
#!/bin/sh
#%# family=manual
#%# capabilities=autoconf suggest
case $1 in
config)
echo graph_category openerp
echo graph_title openerp rpc requests min/average response time
echo graph_vlabel seconds
echo graph_args --units-exponent -3
echo min.label min
echo min.warning 1
echo min.critical 5
echo avg.label average
echo avg.warning 1
echo avg.critical 5
exit 0
;;
esac
# watch out for the time zone of the logs => using date -u for UTC timestamps
result=$(tail -60000 /var/log/openerp.log | grep "object.execute_kw time" | awk "BEGIN{sum=0;count=0} (
$1 " " $2) >= "`date +'%F %H:%M:%S' -ud '5 min ago'`" {split($8,t,":");time=0+t[2];if (min=="") { min=time};
sum += time; count+=1; min=(time>min)?min:time } END{print min, sum/count}")
echo -n "min.value "
echo ${result} | cut -d" " -f1
echo -n "avg.value "
echo ${result} | cut -d" " -f2
exit 0
Munin plugin: OpenERP min/avg response time
t @odony
#!/bin/sh
#%# family=manual
#%# capabilities=autoconf suggest
case $1 in
config)
echo graph_category openerp
echo graph_title openerp rpc requests max response time
echo graph_vlabel seconds
echo graph_args --units-exponent -3
echo max.label max
echo max.warning 1
echo max.critical 5
exit 0
;;..
esac
# watch out for the time zone of the logs => using date -u for UTC timestamps....
result=$(tail -60000 /var/log/openerp.log | grep "object.execute_kw time" | awk "BEGIN{sum=0;count=0} (
$1 " " $2) >= "`date +'%F %H:%M:%S' -ud '85 min ago'`" {split($8,t,":");time=0+t[2]; sum += time; count+=1;
max=(time<max)?max:time } END{print max}")
echo "max.value ${result}"
exit 0
Munin plugin: OpenERP max response time
t @odony
Monitor PostgreSQL
● postgresql.conf
● log_min_duration_statement = 50
● Set to 50 or 100 in production
● Set to 0 to log all queries and execution times for a while
● Instagram gist to capture sample + analyze
● Analyze with pgBadger or pgFouine
●
lc_messages = 'C'
t @odony
PostgreSQL Analysis
● Important PG statistic tables
● pg_stat_activity: near real-time view of transactions
● pg_locks: real-time view of existing locks
● pg_stat_user_tables: generic usage stats for all tables
● pg_statio_user_tables: generic I/O stats for all tables
t @odony
PostgreSQL Analysis: longest tables
# SELECT schemaname || '.' || relname as table,n_live_tup as num_rows
FROM pg_stat_user_tables
ORDER BY n_live_tup DESC limit 10;
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ table β”‚ num_rows β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ public.stock_move β”‚ 179544 β”‚
β”‚ public.ir_translation β”‚ 134039 β”‚
β”‚ public.wkf_workitem β”‚ 97195 β”‚
β”‚ public.wkf_instance β”‚ 96973 β”‚
β”‚ public.procurement_order β”‚ 83077 β”‚
β”‚ public.ir_property β”‚ 69011 β”‚
β”‚ public.ir_model_data β”‚ 59532 β”‚
β”‚ public.stock_move_history_ids β”‚ 58942 β”‚
β”‚ public.mrp_production_move_ids β”‚ 49714 β”‚
β”‚ public.mrp_bom β”‚ 46258 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
t @odony
PostgreSQL Analysis: biggest tables
# SELECT nspname || '.' || relname AS "table",
pg_size_pretty(pg_total_relation_size(C.oid)) AS "total_size"
FROM pg_class C
LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
WHERE nspname NOT IN ('pg_catalog', 'information_schema')
AND C.relkind <> 'i'
AND nspname !~ '^pg_toast'
ORDER BY pg_total_relation_size(C.oid) DESC
LIMIT 10;
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ table β”‚ total_size β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ public.stock_move β”‚ 525 MB β”‚
β”‚ public.wkf_workitem β”‚ 111 MB β”‚
β”‚ public.procurement_order β”‚ 80 MB β”‚
β”‚ public.stock_location β”‚ 63 MB β”‚
β”‚ public.ir_translation β”‚ 42 MB β”‚
β”‚ public.wkf_instance β”‚ 37 MB β”‚
β”‚ public.ir_model_data β”‚ 36 MB β”‚
β”‚ public.ir_property β”‚ 26 MB β”‚
β”‚ public.ir_attachment β”‚ 14 MB β”‚
β”‚ public.mrp_bom β”‚ 13 MB β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
t @odony
PostgreSQL Analysis: biggest tables
●
Consider using the file storage for the
ir.attachment table
●
Avoid storing files in the database
●
Greatly reduces the time needed for DB backups
and backup
●
Very easy to rsync backups of DB dumps +
filestore
●
For 7.0 this setting is explained in this FAQ
t @odony
PostgreSQL Analysis: most read tables
# SELECT schemaname || '.' || relname as table, heap_blks_read as disk_reads,
heap_blks_hit as cache_reads,
heap_blks_read + heap_blks_hit as total_reads
from pg_statio_user_tables
order by heap_blks_read + heap_blks_hit desc limit 15;
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ table β”‚ disk_reads β”‚ cache_reads β”‚ total_reads β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ public.stock_location β”‚ 53796 β”‚ 60926676388 β”‚ 60926730184 β”‚
β”‚ public.stock_move β”‚ 208763 β”‚ 9880525282 β”‚ 9880734045 β”‚
β”‚ public.stock_picking β”‚ 15772 β”‚ 4659569791 β”‚ 4659585563 β”‚
β”‚ public.procurement_order β”‚ 156139 β”‚ 1430660775 β”‚ 1430816914 β”‚
β”‚ public.stock_tracking β”‚ 2621 β”‚ 525023173 β”‚ 525025794 β”‚
β”‚ public.product_product β”‚ 11178 β”‚ 225774346 β”‚ 225785524 β”‚
β”‚ public.mrp_bom β”‚ 27198 β”‚ 225329643 β”‚ 225356841 β”‚
β”‚ public.ir_model_fields β”‚ 1632 β”‚ 203361139 β”‚ 203362771 β”‚
β”‚ public.stock_production_lot β”‚ 5918 β”‚ 127915614 β”‚ 127921532 β”‚
β”‚ public.res_users β”‚ 416 β”‚ 115506586 β”‚ 115507002 β”‚
β”‚ public.ir_model_access β”‚ 6382 β”‚ 104686364 β”‚ 104692746 β”‚
β”‚ public.mrp_production β”‚ 20829 β”‚ 101523983 β”‚ 101544812 β”‚
β”‚ public.product_template β”‚ 4566 β”‚ 76074699 β”‚ 76079265 β”‚
β”‚ public.product_uom β”‚ 18 β”‚ 70521126 β”‚ 70521144 β”‚
β”‚ public.wkf_workitem β”‚ 129166 β”‚ 67782919 β”‚ 67912085 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
t @odony
PostgreSQL Analysis: most updated/inserted/...
# SELECT schemaname || '.' || relname as table,
seq_scan,idx_scan,idx_tup_fetch+seq_tup_read lines_read_total, n_tup_ins as
num_insert,n_tup_upd as num_update,n_tup_del as num_delete
from pg_stat_user_tables order by n_tup_upd desc limit 10;
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ table β”‚ seq_scan β”‚ idx_scan β”‚ lines_read_total β”‚ num_insert β”‚ num_update β”‚ num_delete β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ public.stock_move β”‚ 1188095 β”‚ 1104711719 β”‚ 132030135782 β”‚ 208507 β”‚ 9556574 β”‚ 67298 β”‚
β”‚ public.procurement_order β”‚ 226774 β”‚ 22134417 β”‚ 11794090805 β”‚ 92064 β”‚ 6882666 β”‚ 27543 β”‚
β”‚ public.wkf_workitem β”‚ 373 β”‚ 17340039 β”‚ 29910699 β”‚ 1958392 β”‚ 3280141 β”‚ 1883794 β”‚
β”‚ public.stock_location β”‚ 41402098 β”‚ 166316501 β”‚ 516216409246 β”‚ 97 β”‚ 2215107 β”‚ 205 β”‚
β”‚ public.stock_picking β”‚ 297984 β”‚ 71732467 β”‚ 5671488265 β”‚ 9008 β”‚ 1000966 β”‚ 1954 β”‚
β”‚ public.stock_production_lot β”‚ 190934 β”‚ 28038527 β”‚ 1124560295 β”‚ 4318 β”‚ 722053 β”‚ 0 β”‚
β”‚ public.mrp_production β”‚ 270568 β”‚ 13550371 β”‚ 476534514 β”‚ 3816 β”‚ 495776 β”‚ 1883 β”‚
β”‚ public.sale_order_line β”‚ 30161 β”‚ 4757426 β”‚ 60019207 β”‚ 2077 β”‚ 479752 β”‚ 320 β”‚
β”‚ public.stock_tracking β”‚ 656404 β”‚ 97874788 β”‚ 5054452666 β”‚ 5914 β”‚ 404469 β”‚ 0 β”‚
β”‚ public.ir_cron β”‚ 246636 β”‚ 818 β”‚ 2467441 β”‚ 0 β”‚ 169904 β”‚ 0 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
t @odony
Useful VIEW to watch locked queries
-- For PostgreSQL 9.1
CREATE VIEW monitor_blocked_queries AS
SELECT
pg_class.relname,
waiter.pid as blocked_pid,
substr(wait_act.current_query,1,30) as blocked_statement,
age(now(),wait_act.query_start) as blocked_duration,
holder.pid as blocking_pid,
substr(hold_act.current_query,1,30) as blocking_statement,
age(now(),hold_act.query_start) as blocking_duration,
waiter.transactionid as xid,
waiter.mode as wmode,
waiter.virtualtransaction as wvxid,
holder.mode as hmode,
holder.virtualtransaction as hvxid
FROM pg_locks holder join pg_locks waiter on (
holder.locktype = waiter.locktype and (
holder.database, holder.relation,
holder.page, holder.tuple,
holder.virtualxid,
holder.transactionid, holder.classid,
holder.objid, holder.objsubid
) IS NOT DISTINCT from (
waiter.database, waiter.relation,
waiter.page, waiter.tuple,
waiter.virtualxid,
waiter.transactionid, waiter.classid,
waiter.objid, waiter.objsubid
))
JOIN pg_stat_activity hold_act ON (holder.pid=hold_act.procpid)
JOIN pg_stat_activity wait_act ON (waiter.pid=wait_act.procpid)
LEFT JOIN pg_class ON (holder.relation = pg_class.oid)
WHERE
wait_act.datname = 'eurogerm' AND
holder.granted AND NOT waiter.granted
ORDER BY blocked_duration DESC;
t @odony
Useful VIEW to watch locked queries
# SELECT * FROM blocked_queries;
relname | blocked_pid | blocked_statement | blocked_duration | blocking_pid | blocking_statement
---------+-------------+--------------------------------+------------------+--------------+-------------------------
| 16504 | update "stock_tracking" set "s | 00:00:57.588357 | 16338 | <IDLE> in transaction
| 16501 | update "stock_tracking" set "f | 00:00:55.144373 | 16504 | update "stock_tracking"
(2 lignes)
... | blocking_statement | blocking_duration | xid | wmode | hmode |
... +--------------------------------+-------------------+----------+-----------+---------------|
... | <IDLE> in transaction | -00:00:00.004754 | 12630740 | ShareLock | ExclusiveLock |
... | update "stock_tracking" set "s | 00:00:57.588357 | 12630722 | ShareLock | ExclusiveLock |
t @odony
Useful tool for watching activity: pg_activity
top-like command-line utility to watch queries: running,
blocking, waiting
β†’ pip install pg_activity
Thanks to @cmorisse for this pointer! :-)
t @odony
Useful VIEW to watch Locks per transaction
# – For PostgreSQL 9.1
# CREATE VIEW monitor_locks AS
SELECT pg_stat_activity.procpid, pg_class.relname, pg_locks.locktype,
pg_locks.transactionid, pg_locks.virtualxid,
pg_locks.virtualtransaction, pg_locks.mode, pg_locks.granted,
pg_stat_activity.usename,
substr(pg_stat_activity.current_query,1,30) AS query,
pg_stat_activity.query_start, age(now(),pg_stat_activity.query_start)
AS duration
FROM pg_stat_activity, pg_locks
LEFT JOIN pg_class ON pg_locks.relation = pg_class.oid
WHERE pg_locks.pid = pg_stat_activity.procpid AND
pg_stat_activity.procpid != pg_backend_pid()
ORDER BY pg_stat_activity.procpid, pg_locks.granted, pg_class.relname;
t @odony
Useful VIEW to watch Locks per transaction
pid | relname | locktype | xid | virtualxid
------+-----------------------------------------------------------+------------------+----------+-----------
8597 | | transactionid | 12171567 | 11/164037
8597 | purchase_order_line_pkey | relation | | 11/164037
8597 | stock_location_location_id_index | relation | | 11/164037
8597 | stock_move_production_id_index | relation | | 11/164037
8597 | stock_move_production_id_index | relation | | 11/164037
8597 | stock_move_location_id_location_dest_id_product_id_state | relation | | 11/164037
8597 | multi_company_default | relation | | 11/164037
8597 | stock_picking_invoice_state_index | relation | | 11/164037
8597 | ir_model_access_group_id_index | relation | | 11/164037
8597 | purchase_order_line_date_planned_index | relation | | 11/164037
8597 | purchase_order_pkey | relation | | 11/164037
8597 | res_company | relation | | 11/164037
8597 | purchase_order_name_index | relation | | 11/164037
8597 | res_company | relation | | 11/164037
8597 | ir_sequence_pkey | relation | | 11/164037
8597 | ir_sequence_pkey | relation | | 11/164037
8597 | res_partner_company_id_index | relation | | 11/164037
8597 | product_product_have_pqcd_cde_index | relation | | 11/164037
8597 | stock_tracking | relation | | 11/164037
8597 | ir_translation_src_hash_idx | relation | | 11/164037
8597 | res_users | relation | | 11/164037
8597 | product_template_name_index | relation | | 11/164037
8597 | res_users | relation | | 11/164037
8597 | stock_move_tracking
t @odony
Useful VIEW to watch Locks per transaction
| mode | granted | query | query_start | duration |
+------------------+---------+--------------------------------+-------------------------------+------------------+
| AccessShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 |
| AccessShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 |
| AccessShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 |
| AccessShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 |
| RowExclusiveLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 |
| AccessShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 |
| AccessShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 |
| AccessShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 |
| AccessShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 |
| AccessShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 |
| AccessShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 |
| AccessShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 |
| AccessShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 |
| RowShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 |
| AccessShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 |
| RowExclusiveLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 |
| AccessShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 |
| AccessShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 |
| AccessShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 |
| AccessShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 |
| RowShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 |
| AccessShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 |
| AccessShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 |
t @odony
Normal Values?
● Most RPC requests should be under 200ms
● Most SQL queries should be under 100ms
● One transaction = 100-300 heavyweight locks
Find your own normal values via monitoring!
t @odony
Agenda
● Architecture / Deployment / Sizing
● Measuring & Analyzing
● Common Problems
● Anti-patterns
t @odony
Common Problems
● Stored functions
● Slow Queries/Views, Suboptimal domains
● Lock contention
● Custom locking mechanisms (queues, locks,...)
t @odony
Common Problems: Stored Functions
● Stored functional fields are triggers
● Store triggers can be:
●
store = { 'trigger_model': (mapping_function,
['trigger_field1', 'trigger_field2'],
priority) }
● store=True meaning:
self._name (lambda s,c,u,ids,c: ids, None, 10)}β†’
● Can be very expensive with wrong parameters or
slow functions
t @odony
Common Problems: Slow Queries
●
All SQL queries 500ms+ should be analyzed
●
Use EXPLAIN ANALYZE to examine/measure you custom
SQL queries and VIEWs
●
Try to remove parts of the query until it's fast, then fix it
●
Check cardinality of big JOINs
●
Default domain evaluation strategy
●
search([('picking_id.move_ids.partner_id', '!=', False)])
●
Implemented by combining β€œid IN (….)” parts
●
Have a look at _auto_join in OpenERP 7.0
'move_ids': fields.one2many('stock.move', 'picking_id',
string='Moves', _auto_join=True)
t @odony
Common Problems: Slow Queries
● No premature optimization: don't write SQL,
use the ORM always during initial
development
● If you detect a hot spot with load-tests,
consider rewriting the inefficient parts in SQL
● But:
● Make sure you're not bypassing security mechanisms
● Don't create SQL injection vectors use query parameters,β†’
don't concatenate user input in your SQL strings.
t @odony
Common Problems: Lock Contention
●
PostgreSQL guarantees transactional data integrity by
taking heavy-weight locks β†’ monitor_locks
●
Updating a record blocks all FK locks on it until the
transaction is completed!
●
This will change with PostgreSQL 9.3 :-)
●
This is independent from the transaction isolation level
(Repeatable Read/Serializable/...)
β†’ Don't have long-running transactions!
β†’ Avoid updating β€œmaster data” resources in them!
(user, company, stock location, product, …)
t @odony
Common Problems: Custom Locking
●
Any kind of manual locking/queuing mechanism
is dangerous, especially in Python
●
Python locks can cause deadlocks that cannot
be detected and broken by the system!
●
Avoid it, and if you must, use the database as
lock
●
That's what scheduled jobs (ir.cron) do:
●
SELECT FOR UPDATE on the cron job row
●
β†’ Automatic cleanup/release
●
β†’ Scales well and works in multi-process!
t @odony
Agenda
● Architecture / Deployment / Sizing
● Measuring & Analyzing
● Common Problems
● Anti-patterns
t @odony
Avoid Anti-Patterns: Master the framework!
●
Make sure you really understand the browse()
mechanisms!
●
Make sure you properly use the batch API
●
Don't write SQL unless you have to, e.g for:
●
Analysis views
●
Hot spot functions, name_search(), computed_fields(), ...
t @odony
Anti-Patterns: what's wrong?
browse() must be used on lists to benefit from its optimizations!
t @odony
Anti-Patterns: what's wrong now?
browse() use is OK now, but the related field is dangerous
and costly, going through a possibly very large o2m just to find
a single product ID
t @odony
Anti-Patterns: what's wrong here?
The trigger on stock.move is for all fields which means it will
trigger for each change, while we only care about tracking_id
here

Weitere Γ€hnliche Inhalte

Was ist angesagt?

Odoo Online platform: architecture and challenges
Odoo Online platform: architecture and challengesOdoo Online platform: architecture and challenges
Odoo Online platform: architecture and challengesOdoo
Β 
Odoo's Test Framework - Learn Best Practices
Odoo's Test Framework - Learn Best PracticesOdoo's Test Framework - Learn Best Practices
Odoo's Test Framework - Learn Best PracticesOdoo
Β 
Common Performance Pitfalls in Odoo apps
Common Performance Pitfalls in Odoo appsCommon Performance Pitfalls in Odoo apps
Common Performance Pitfalls in Odoo appsOdoo
Β 
Simple Odoo ERP auto scaling on AWS
Simple Odoo ERP auto scaling on AWSSimple Odoo ERP auto scaling on AWS
Simple Odoo ERP auto scaling on AWSJulien Lecadou,MSc.
Β 
Impact of the New ORM on Your Modules
Impact of the New ORM on Your ModulesImpact of the New ORM on Your Modules
Impact of the New ORM on Your ModulesOdoo
Β 
New Framework - ORM
New Framework - ORMNew Framework - ORM
New Framework - ORMOdoo
Β 
Deep dive into PostgreSQL statistics.
Deep dive into PostgreSQL statistics.Deep dive into PostgreSQL statistics.
Deep dive into PostgreSQL statistics.Alexey Lesovsky
Β 
My first 90 days with ClickHouse.pdf
My first 90 days with ClickHouse.pdfMy first 90 days with ClickHouse.pdf
My first 90 days with ClickHouse.pdfAlkin Tezuysal
Β 
Asynchronous JS in Odoo
Asynchronous JS in OdooAsynchronous JS in Odoo
Asynchronous JS in OdooOdoo
Β 
All About JSON and ClickHouse - Tips, Tricks and New Features-2022-07-26-FINA...
All About JSON and ClickHouse - Tips, Tricks and New Features-2022-07-26-FINA...All About JSON and ClickHouse - Tips, Tricks and New Features-2022-07-26-FINA...
All About JSON and ClickHouse - Tips, Tricks and New Features-2022-07-26-FINA...Altinity Ltd
Β 
Monolith vs Microservices with Golang at practice - Ivan Kutuzov
Monolith vs Microservices with Golang at practice  -  Ivan Kutuzov Monolith vs Microservices with Golang at practice  -  Ivan Kutuzov
Monolith vs Microservices with Golang at practice - Ivan Kutuzov Kuberton
Β 
Discover GraphQL with Python, Graphene and Odoo
Discover GraphQL with Python, Graphene and OdooDiscover GraphQL with Python, Graphene and Odoo
Discover GraphQL with Python, Graphene and OdooOdoo
Β 
MySQL 8.0.16 New Features Summary
MySQL 8.0.16 New Features SummaryMySQL 8.0.16 New Features Summary
MySQL 8.0.16 New Features SummaryOlivier DASINI
Β 
Why and how to develop OpenERP test scenarios (in python and using OERPScenar...
Why and how to develop OpenERP test scenarios (in python and using OERPScenar...Why and how to develop OpenERP test scenarios (in python and using OERPScenar...
Why and how to develop OpenERP test scenarios (in python and using OERPScenar...Odoo
Β 
Apache Airflow in Production
Apache Airflow in ProductionApache Airflow in Production
Apache Airflow in ProductionRobert Sanders
Β 
The Odoo JS Framework
The Odoo JS FrameworkThe Odoo JS Framework
The Odoo JS FrameworkOdoo
Β 
Using Kamailio for Scalability and Security
Using Kamailio for Scalability and SecurityUsing Kamailio for Scalability and Security
Using Kamailio for Scalability and SecurityFred Posner
Β 

Was ist angesagt? (20)

Odoo Online platform: architecture and challenges
Odoo Online platform: architecture and challengesOdoo Online platform: architecture and challenges
Odoo Online platform: architecture and challenges
Β 
Odoo's Test Framework - Learn Best Practices
Odoo's Test Framework - Learn Best PracticesOdoo's Test Framework - Learn Best Practices
Odoo's Test Framework - Learn Best Practices
Β 
Common Performance Pitfalls in Odoo apps
Common Performance Pitfalls in Odoo appsCommon Performance Pitfalls in Odoo apps
Common Performance Pitfalls in Odoo apps
Β 
Simple Odoo ERP auto scaling on AWS
Simple Odoo ERP auto scaling on AWSSimple Odoo ERP auto scaling on AWS
Simple Odoo ERP auto scaling on AWS
Β 
Impact of the New ORM on Your Modules
Impact of the New ORM on Your ModulesImpact of the New ORM on Your Modules
Impact of the New ORM on Your Modules
Β 
New Framework - ORM
New Framework - ORMNew Framework - ORM
New Framework - ORM
Β 
Deep dive into PostgreSQL statistics.
Deep dive into PostgreSQL statistics.Deep dive into PostgreSQL statistics.
Deep dive into PostgreSQL statistics.
Β 
My first 90 days with ClickHouse.pdf
My first 90 days with ClickHouse.pdfMy first 90 days with ClickHouse.pdf
My first 90 days with ClickHouse.pdf
Β 
Asynchronous JS in Odoo
Asynchronous JS in OdooAsynchronous JS in Odoo
Asynchronous JS in Odoo
Β 
All About JSON and ClickHouse - Tips, Tricks and New Features-2022-07-26-FINA...
All About JSON and ClickHouse - Tips, Tricks and New Features-2022-07-26-FINA...All About JSON and ClickHouse - Tips, Tricks and New Features-2022-07-26-FINA...
All About JSON and ClickHouse - Tips, Tricks and New Features-2022-07-26-FINA...
Β 
Monolith vs Microservices with Golang at practice - Ivan Kutuzov
Monolith vs Microservices with Golang at practice  -  Ivan Kutuzov Monolith vs Microservices with Golang at practice  -  Ivan Kutuzov
Monolith vs Microservices with Golang at practice - Ivan Kutuzov
Β 
Discover GraphQL with Python, Graphene and Odoo
Discover GraphQL with Python, Graphene and OdooDiscover GraphQL with Python, Graphene and Odoo
Discover GraphQL with Python, Graphene and Odoo
Β 
MySQL 8.0.16 New Features Summary
MySQL 8.0.16 New Features SummaryMySQL 8.0.16 New Features Summary
MySQL 8.0.16 New Features Summary
Β 
Why and how to develop OpenERP test scenarios (in python and using OERPScenar...
Why and how to develop OpenERP test scenarios (in python and using OERPScenar...Why and how to develop OpenERP test scenarios (in python and using OERPScenar...
Why and how to develop OpenERP test scenarios (in python and using OERPScenar...
Β 
Odoo Experience 2018 - Code Profiling in Odoo
Odoo Experience 2018 - Code Profiling in OdooOdoo Experience 2018 - Code Profiling in Odoo
Odoo Experience 2018 - Code Profiling in Odoo
Β 
Apache Airflow in Production
Apache Airflow in ProductionApache Airflow in Production
Apache Airflow in Production
Β 
Concurrency With Go
Concurrency With GoConcurrency With Go
Concurrency With Go
Β 
The Odoo JS Framework
The Odoo JS FrameworkThe Odoo JS Framework
The Odoo JS Framework
Β 
Using Kamailio for Scalability and Security
Using Kamailio for Scalability and SecurityUsing Kamailio for Scalability and Security
Using Kamailio for Scalability and Security
Β 
Odoo
OdooOdoo
Odoo
Β 

Γ„hnlich wie Tips on how to improve the performance of your custom modules for high volumes deployment. Olivier Dony, OpenERP

Nginx Scripting - Extending Nginx Functionalities with Lua
Nginx Scripting - Extending Nginx Functionalities with LuaNginx Scripting - Extending Nginx Functionalities with Lua
Nginx Scripting - Extending Nginx Functionalities with LuaTony Fabeen
Β 
Devinsampa nginx-scripting
Devinsampa nginx-scriptingDevinsampa nginx-scripting
Devinsampa nginx-scriptingTony Fabeen
Β 
Application Logging in the 21st century - 2014.key
Application Logging in the 21st century - 2014.keyApplication Logging in the 21st century - 2014.key
Application Logging in the 21st century - 2014.keyTim Bunce
Β 
Node.js Event Loop & EventEmitter
Node.js Event Loop & EventEmitterNode.js Event Loop & EventEmitter
Node.js Event Loop & EventEmitterSimen Li
Β 
11 Things About 11gr2
11 Things About 11gr211 Things About 11gr2
11 Things About 11gr2afa reg
Β 
Speed up R with parallel programming in the Cloud
Speed up R with parallel programming in the CloudSpeed up R with parallel programming in the Cloud
Speed up R with parallel programming in the CloudRevolution Analytics
Β 
Introduction to Java Profiling
Introduction to Java ProfilingIntroduction to Java Profiling
Introduction to Java ProfilingJerry Yoakum
Β 
Splunk conf2014 - Lesser Known Commands in Splunk Search Processing Language ...
Splunk conf2014 - Lesser Known Commands in Splunk Search Processing Language ...Splunk conf2014 - Lesser Known Commands in Splunk Search Processing Language ...
Splunk conf2014 - Lesser Known Commands in Splunk Search Processing Language ...Splunk
Β 
Ceph Day Melbourne - Troubleshooting Ceph
Ceph Day Melbourne - Troubleshooting Ceph Ceph Day Melbourne - Troubleshooting Ceph
Ceph Day Melbourne - Troubleshooting Ceph Ceph Community
Β 
OSMC 2012 | Neues in Nagios 4.0 by Andreas Ericsson
OSMC 2012 | Neues in Nagios 4.0 by Andreas EricssonOSMC 2012 | Neues in Nagios 4.0 by Andreas Ericsson
OSMC 2012 | Neues in Nagios 4.0 by Andreas EricssonNETWAYS
Β 
Dynamic Tracing of your AMP web site
Dynamic Tracing of your AMP web siteDynamic Tracing of your AMP web site
Dynamic Tracing of your AMP web siteSriram Natarajan
Β 
HC-4021, Efficient scheduling of OpenMP and OpenCLβ„’ workloads on Accelerated ...
HC-4021, Efficient scheduling of OpenMP and OpenCLβ„’ workloads on Accelerated ...HC-4021, Efficient scheduling of OpenMP and OpenCLβ„’ workloads on Accelerated ...
HC-4021, Efficient scheduling of OpenMP and OpenCLβ„’ workloads on Accelerated ...AMD Developer Central
Β 
SplunkLive! Washington DC May 2013 - Splunk Security Workshop
SplunkLive! Washington DC May 2013 - Splunk Security WorkshopSplunkLive! Washington DC May 2013 - Splunk Security Workshop
SplunkLive! Washington DC May 2013 - Splunk Security WorkshopSplunk
Β 
Optimizing Performance - Clojure Remote - Nikola Peric
Optimizing Performance - Clojure Remote - Nikola PericOptimizing Performance - Clojure Remote - Nikola Peric
Optimizing Performance - Clojure Remote - Nikola PericNik Peric
Β 
Linux Systems Performance 2016
Linux Systems Performance 2016Linux Systems Performance 2016
Linux Systems Performance 2016Brendan Gregg
Β 
Docker Logging and analysing with Elastic Stack - Jakub Hajek
Docker Logging and analysing with Elastic Stack - Jakub Hajek Docker Logging and analysing with Elastic Stack - Jakub Hajek
Docker Logging and analysing with Elastic Stack - Jakub Hajek PROIDEA
Β 

Γ„hnlich wie Tips on how to improve the performance of your custom modules for high volumes deployment. Olivier Dony, OpenERP (20)

Nginx Scripting - Extending Nginx Functionalities with Lua
Nginx Scripting - Extending Nginx Functionalities with LuaNginx Scripting - Extending Nginx Functionalities with Lua
Nginx Scripting - Extending Nginx Functionalities with Lua
Β 
Devinsampa nginx-scripting
Devinsampa nginx-scriptingDevinsampa nginx-scripting
Devinsampa nginx-scripting
Β 
Osol Pgsql
Osol PgsqlOsol Pgsql
Osol Pgsql
Β 
Application Logging in the 21st century - 2014.key
Application Logging in the 21st century - 2014.keyApplication Logging in the 21st century - 2014.key
Application Logging in the 21st century - 2014.key
Β 
Node.js Event Loop & EventEmitter
Node.js Event Loop & EventEmitterNode.js Event Loop & EventEmitter
Node.js Event Loop & EventEmitter
Β 
11 Things About 11gr2
11 Things About 11gr211 Things About 11gr2
11 Things About 11gr2
Β 
Speed up R with parallel programming in the Cloud
Speed up R with parallel programming in the CloudSpeed up R with parallel programming in the Cloud
Speed up R with parallel programming in the Cloud
Β 
sun solaris
sun solarissun solaris
sun solaris
Β 
Introduction to Java Profiling
Introduction to Java ProfilingIntroduction to Java Profiling
Introduction to Java Profiling
Β 
Splunk conf2014 - Lesser Known Commands in Splunk Search Processing Language ...
Splunk conf2014 - Lesser Known Commands in Splunk Search Processing Language ...Splunk conf2014 - Lesser Known Commands in Splunk Search Processing Language ...
Splunk conf2014 - Lesser Known Commands in Splunk Search Processing Language ...
Β 
Ceph Day Melbourne - Troubleshooting Ceph
Ceph Day Melbourne - Troubleshooting Ceph Ceph Day Melbourne - Troubleshooting Ceph
Ceph Day Melbourne - Troubleshooting Ceph
Β 
OSMC 2012 | Neues in Nagios 4.0 by Andreas Ericsson
OSMC 2012 | Neues in Nagios 4.0 by Andreas EricssonOSMC 2012 | Neues in Nagios 4.0 by Andreas Ericsson
OSMC 2012 | Neues in Nagios 4.0 by Andreas Ericsson
Β 
Bioinformatica p4-io
Bioinformatica p4-ioBioinformatica p4-io
Bioinformatica p4-io
Β 
Dynamic Tracing of your AMP web site
Dynamic Tracing of your AMP web siteDynamic Tracing of your AMP web site
Dynamic Tracing of your AMP web site
Β 
HC-4021, Efficient scheduling of OpenMP and OpenCLβ„’ workloads on Accelerated ...
HC-4021, Efficient scheduling of OpenMP and OpenCLβ„’ workloads on Accelerated ...HC-4021, Efficient scheduling of OpenMP and OpenCLβ„’ workloads on Accelerated ...
HC-4021, Efficient scheduling of OpenMP and OpenCLβ„’ workloads on Accelerated ...
Β 
SplunkLive! Washington DC May 2013 - Splunk Security Workshop
SplunkLive! Washington DC May 2013 - Splunk Security WorkshopSplunkLive! Washington DC May 2013 - Splunk Security Workshop
SplunkLive! Washington DC May 2013 - Splunk Security Workshop
Β 
Optimizing Performance - Clojure Remote - Nikola Peric
Optimizing Performance - Clojure Remote - Nikola PericOptimizing Performance - Clojure Remote - Nikola Peric
Optimizing Performance - Clojure Remote - Nikola Peric
Β 
pm1
pm1pm1
pm1
Β 
Linux Systems Performance 2016
Linux Systems Performance 2016Linux Systems Performance 2016
Linux Systems Performance 2016
Β 
Docker Logging and analysing with Elastic Stack - Jakub Hajek
Docker Logging and analysing with Elastic Stack - Jakub Hajek Docker Logging and analysing with Elastic Stack - Jakub Hajek
Docker Logging and analysing with Elastic Stack - Jakub Hajek
Β 

Mehr von Odoo

Timesheet Workshop: The Timesheet App People Love!
Timesheet Workshop: The Timesheet App People Love!Timesheet Workshop: The Timesheet App People Love!
Timesheet Workshop: The Timesheet App People Love!Odoo
Β 
Odoo 3D Product View with Google Model-Viewer
Odoo 3D Product View with Google Model-ViewerOdoo 3D Product View with Google Model-Viewer
Odoo 3D Product View with Google Model-ViewerOdoo
Β 
Keynote - Vision & Strategy
Keynote - Vision & StrategyKeynote - Vision & Strategy
Keynote - Vision & StrategyOdoo
Β 
Opening Keynote - Unveilling Odoo 14
Opening Keynote - Unveilling Odoo 14Opening Keynote - Unveilling Odoo 14
Opening Keynote - Unveilling Odoo 14Odoo
Β 
Extending Odoo with a Comprehensive Budgeting and Forecasting Capability
Extending Odoo with a Comprehensive Budgeting and Forecasting CapabilityExtending Odoo with a Comprehensive Budgeting and Forecasting Capability
Extending Odoo with a Comprehensive Budgeting and Forecasting CapabilityOdoo
Β 
Managing Multi-channel Selling with Odoo
Managing Multi-channel Selling with OdooManaging Multi-channel Selling with Odoo
Managing Multi-channel Selling with OdooOdoo
Β 
Product Configurator: Advanced Use Case
Product Configurator: Advanced Use CaseProduct Configurator: Advanced Use Case
Product Configurator: Advanced Use CaseOdoo
Β 
Accounting Automation: How Much Money We Saved and How?
Accounting Automation: How Much Money We Saved and How?Accounting Automation: How Much Money We Saved and How?
Accounting Automation: How Much Money We Saved and How?Odoo
Β 
Rock Your Logistics with Advanced Operations
Rock Your Logistics with Advanced OperationsRock Your Logistics with Advanced Operations
Rock Your Logistics with Advanced OperationsOdoo
Β 
Transition from a cost to a flow-centric organization
Transition from a cost to a flow-centric organizationTransition from a cost to a flow-centric organization
Transition from a cost to a flow-centric organizationOdoo
Β 
Synchronization: The Supply Chain Response to Overcome the Crisis
Synchronization: The Supply Chain Response to Overcome the CrisisSynchronization: The Supply Chain Response to Overcome the Crisis
Synchronization: The Supply Chain Response to Overcome the CrisisOdoo
Β 
Running a University with Odoo
Running a University with OdooRunning a University with Odoo
Running a University with OdooOdoo
Β 
Down Payments on Purchase Orders in Odoo
Down Payments on Purchase Orders in OdooDown Payments on Purchase Orders in Odoo
Down Payments on Purchase Orders in OdooOdoo
Β 
Odoo Implementation in Phases - Success Story of a Retail Chain 3Sach food
Odoo Implementation in Phases - Success Story of a Retail Chain 3Sach foodOdoo Implementation in Phases - Success Story of a Retail Chain 3Sach food
Odoo Implementation in Phases - Success Story of a Retail Chain 3Sach foodOdoo
Β 
Migration from Salesforce to Odoo
Migration from Salesforce to OdooMigration from Salesforce to Odoo
Migration from Salesforce to OdooOdoo
Β 
Preventing User Mistakes by Using Machine Learning
Preventing User Mistakes by Using Machine LearningPreventing User Mistakes by Using Machine Learning
Preventing User Mistakes by Using Machine LearningOdoo
Β 
Becoming an Odoo Expert: How to Prepare for the Certification
Becoming an Odoo Expert: How to Prepare for the Certification Becoming an Odoo Expert: How to Prepare for the Certification
Becoming an Odoo Expert: How to Prepare for the Certification Odoo
Β 
Instant Printing of any Odoo Report or Shipping Label
Instant Printing of any Odoo Report or Shipping LabelInstant Printing of any Odoo Report or Shipping Label
Instant Printing of any Odoo Report or Shipping LabelOdoo
Β 
How Odoo helped an Organization Grow 3 Fold
How Odoo helped an Organization Grow 3 FoldHow Odoo helped an Organization Grow 3 Fold
How Odoo helped an Organization Grow 3 FoldOdoo
Β 
From Shopify to Odoo
From Shopify to OdooFrom Shopify to Odoo
From Shopify to OdooOdoo
Β 

Mehr von Odoo (20)

Timesheet Workshop: The Timesheet App People Love!
Timesheet Workshop: The Timesheet App People Love!Timesheet Workshop: The Timesheet App People Love!
Timesheet Workshop: The Timesheet App People Love!
Β 
Odoo 3D Product View with Google Model-Viewer
Odoo 3D Product View with Google Model-ViewerOdoo 3D Product View with Google Model-Viewer
Odoo 3D Product View with Google Model-Viewer
Β 
Keynote - Vision & Strategy
Keynote - Vision & StrategyKeynote - Vision & Strategy
Keynote - Vision & Strategy
Β 
Opening Keynote - Unveilling Odoo 14
Opening Keynote - Unveilling Odoo 14Opening Keynote - Unveilling Odoo 14
Opening Keynote - Unveilling Odoo 14
Β 
Extending Odoo with a Comprehensive Budgeting and Forecasting Capability
Extending Odoo with a Comprehensive Budgeting and Forecasting CapabilityExtending Odoo with a Comprehensive Budgeting and Forecasting Capability
Extending Odoo with a Comprehensive Budgeting and Forecasting Capability
Β 
Managing Multi-channel Selling with Odoo
Managing Multi-channel Selling with OdooManaging Multi-channel Selling with Odoo
Managing Multi-channel Selling with Odoo
Β 
Product Configurator: Advanced Use Case
Product Configurator: Advanced Use CaseProduct Configurator: Advanced Use Case
Product Configurator: Advanced Use Case
Β 
Accounting Automation: How Much Money We Saved and How?
Accounting Automation: How Much Money We Saved and How?Accounting Automation: How Much Money We Saved and How?
Accounting Automation: How Much Money We Saved and How?
Β 
Rock Your Logistics with Advanced Operations
Rock Your Logistics with Advanced OperationsRock Your Logistics with Advanced Operations
Rock Your Logistics with Advanced Operations
Β 
Transition from a cost to a flow-centric organization
Transition from a cost to a flow-centric organizationTransition from a cost to a flow-centric organization
Transition from a cost to a flow-centric organization
Β 
Synchronization: The Supply Chain Response to Overcome the Crisis
Synchronization: The Supply Chain Response to Overcome the CrisisSynchronization: The Supply Chain Response to Overcome the Crisis
Synchronization: The Supply Chain Response to Overcome the Crisis
Β 
Running a University with Odoo
Running a University with OdooRunning a University with Odoo
Running a University with Odoo
Β 
Down Payments on Purchase Orders in Odoo
Down Payments on Purchase Orders in OdooDown Payments on Purchase Orders in Odoo
Down Payments on Purchase Orders in Odoo
Β 
Odoo Implementation in Phases - Success Story of a Retail Chain 3Sach food
Odoo Implementation in Phases - Success Story of a Retail Chain 3Sach foodOdoo Implementation in Phases - Success Story of a Retail Chain 3Sach food
Odoo Implementation in Phases - Success Story of a Retail Chain 3Sach food
Β 
Migration from Salesforce to Odoo
Migration from Salesforce to OdooMigration from Salesforce to Odoo
Migration from Salesforce to Odoo
Β 
Preventing User Mistakes by Using Machine Learning
Preventing User Mistakes by Using Machine LearningPreventing User Mistakes by Using Machine Learning
Preventing User Mistakes by Using Machine Learning
Β 
Becoming an Odoo Expert: How to Prepare for the Certification
Becoming an Odoo Expert: How to Prepare for the Certification Becoming an Odoo Expert: How to Prepare for the Certification
Becoming an Odoo Expert: How to Prepare for the Certification
Β 
Instant Printing of any Odoo Report or Shipping Label
Instant Printing of any Odoo Report or Shipping LabelInstant Printing of any Odoo Report or Shipping Label
Instant Printing of any Odoo Report or Shipping Label
Β 
How Odoo helped an Organization Grow 3 Fold
How Odoo helped an Organization Grow 3 FoldHow Odoo helped an Organization Grow 3 Fold
How Odoo helped an Organization Grow 3 Fold
Β 
From Shopify to Odoo
From Shopify to OdooFrom Shopify to Odoo
From Shopify to Odoo
Β 

KΓΌrzlich hochgeladen

Youth Involvement in an Innovative Coconut Value Chain by Mwalimu Menza
Youth Involvement in an Innovative Coconut Value Chain by Mwalimu MenzaYouth Involvement in an Innovative Coconut Value Chain by Mwalimu Menza
Youth Involvement in an Innovative Coconut Value Chain by Mwalimu Menzaictsugar
Β 
Darshan Hiranandani [News About Next CEO].pdf
Darshan Hiranandani [News About Next CEO].pdfDarshan Hiranandani [News About Next CEO].pdf
Darshan Hiranandani [News About Next CEO].pdfShashank Mehta
Β 
TriStar Gold Corporate Presentation - April 2024
TriStar Gold Corporate Presentation - April 2024TriStar Gold Corporate Presentation - April 2024
TriStar Gold Corporate Presentation - April 2024Adnet Communications
Β 
Church Building Grants To Assist With New Construction, Additions, And Restor...
Church Building Grants To Assist With New Construction, Additions, And Restor...Church Building Grants To Assist With New Construction, Additions, And Restor...
Church Building Grants To Assist With New Construction, Additions, And Restor...Americas Got Grants
Β 
(Best) ENJOY Call Girls in Faridabad Ex | 8377087607
(Best) ENJOY Call Girls in Faridabad Ex | 8377087607(Best) ENJOY Call Girls in Faridabad Ex | 8377087607
(Best) ENJOY Call Girls in Faridabad Ex | 8377087607dollysharma2066
Β 
Call US-88OO1O2216 Call Girls In Mahipalpur Female Escort Service
Call US-88OO1O2216 Call Girls In Mahipalpur Female Escort ServiceCall US-88OO1O2216 Call Girls In Mahipalpur Female Escort Service
Call US-88OO1O2216 Call Girls In Mahipalpur Female Escort Servicecallgirls2057
Β 
8447779800, Low rate Call girls in Shivaji Enclave Delhi NCR
8447779800, Low rate Call girls in Shivaji Enclave Delhi NCR8447779800, Low rate Call girls in Shivaji Enclave Delhi NCR
8447779800, Low rate Call girls in Shivaji Enclave Delhi NCRashishs7044
Β 
Kenya Coconut Production Presentation by Dr. Lalith Perera
Kenya Coconut Production Presentation by Dr. Lalith PereraKenya Coconut Production Presentation by Dr. Lalith Perera
Kenya Coconut Production Presentation by Dr. Lalith Pereraictsugar
Β 
Buy gmail accounts.pdf Buy Old Gmail Accounts
Buy gmail accounts.pdf Buy Old Gmail AccountsBuy gmail accounts.pdf Buy Old Gmail Accounts
Buy gmail accounts.pdf Buy Old Gmail AccountsBuy Verified Accounts
Β 
Innovation Conference 5th March 2024.pdf
Innovation Conference 5th March 2024.pdfInnovation Conference 5th March 2024.pdf
Innovation Conference 5th March 2024.pdfrichard876048
Β 
The-Ethical-issues-ghhhhhhhhjof-Byjus.pptx
The-Ethical-issues-ghhhhhhhhjof-Byjus.pptxThe-Ethical-issues-ghhhhhhhhjof-Byjus.pptx
The-Ethical-issues-ghhhhhhhhjof-Byjus.pptxmbikashkanyari
Β 
Call Us πŸ“²8800102216πŸ“ž Call Girls In DLF City Gurgaon
Call Us πŸ“²8800102216πŸ“ž Call Girls In DLF City GurgaonCall Us πŸ“²8800102216πŸ“ž Call Girls In DLF City Gurgaon
Call Us πŸ“²8800102216πŸ“ž Call Girls In DLF City Gurgaoncallgirls2057
Β 
Unlocking the Future: Explore Web 3.0 Workshop to Start Earning Today!
Unlocking the Future: Explore Web 3.0 Workshop to Start Earning Today!Unlocking the Future: Explore Web 3.0 Workshop to Start Earning Today!
Unlocking the Future: Explore Web 3.0 Workshop to Start Earning Today!Doge Mining Website
Β 
Flow Your Strategy at Flight Levels Day 2024
Flow Your Strategy at Flight Levels Day 2024Flow Your Strategy at Flight Levels Day 2024
Flow Your Strategy at Flight Levels Day 2024Kirill Klimov
Β 
Pitch Deck Teardown: Geodesic.Life's $500k Pre-seed deck
Pitch Deck Teardown: Geodesic.Life's $500k Pre-seed deckPitch Deck Teardown: Geodesic.Life's $500k Pre-seed deck
Pitch Deck Teardown: Geodesic.Life's $500k Pre-seed deckHajeJanKamps
Β 
8447779800, Low rate Call girls in Uttam Nagar Delhi NCR
8447779800, Low rate Call girls in Uttam Nagar Delhi NCR8447779800, Low rate Call girls in Uttam Nagar Delhi NCR
8447779800, Low rate Call girls in Uttam Nagar Delhi NCRashishs7044
Β 
Guide Complete Set of Residential Architectural Drawings PDF
Guide Complete Set of Residential Architectural Drawings PDFGuide Complete Set of Residential Architectural Drawings PDF
Guide Complete Set of Residential Architectural Drawings PDFChandresh Chudasama
Β 
NewBase 19 April 2024 Energy News issue - 1717 by Khaled Al Awadi.pdf
NewBase  19 April  2024  Energy News issue - 1717 by Khaled Al Awadi.pdfNewBase  19 April  2024  Energy News issue - 1717 by Khaled Al Awadi.pdf
NewBase 19 April 2024 Energy News issue - 1717 by Khaled Al Awadi.pdfKhaled Al Awadi
Β 
Marketplace and Quality Assurance Presentation - Vincent Chirchir
Marketplace and Quality Assurance Presentation - Vincent ChirchirMarketplace and Quality Assurance Presentation - Vincent Chirchir
Marketplace and Quality Assurance Presentation - Vincent Chirchirictsugar
Β 
Kenya’s Coconut Value Chain by Gatsby Africa
Kenya’s Coconut Value Chain by Gatsby AfricaKenya’s Coconut Value Chain by Gatsby Africa
Kenya’s Coconut Value Chain by Gatsby Africaictsugar
Β 

KΓΌrzlich hochgeladen (20)

Youth Involvement in an Innovative Coconut Value Chain by Mwalimu Menza
Youth Involvement in an Innovative Coconut Value Chain by Mwalimu MenzaYouth Involvement in an Innovative Coconut Value Chain by Mwalimu Menza
Youth Involvement in an Innovative Coconut Value Chain by Mwalimu Menza
Β 
Darshan Hiranandani [News About Next CEO].pdf
Darshan Hiranandani [News About Next CEO].pdfDarshan Hiranandani [News About Next CEO].pdf
Darshan Hiranandani [News About Next CEO].pdf
Β 
TriStar Gold Corporate Presentation - April 2024
TriStar Gold Corporate Presentation - April 2024TriStar Gold Corporate Presentation - April 2024
TriStar Gold Corporate Presentation - April 2024
Β 
Church Building Grants To Assist With New Construction, Additions, And Restor...
Church Building Grants To Assist With New Construction, Additions, And Restor...Church Building Grants To Assist With New Construction, Additions, And Restor...
Church Building Grants To Assist With New Construction, Additions, And Restor...
Β 
(Best) ENJOY Call Girls in Faridabad Ex | 8377087607
(Best) ENJOY Call Girls in Faridabad Ex | 8377087607(Best) ENJOY Call Girls in Faridabad Ex | 8377087607
(Best) ENJOY Call Girls in Faridabad Ex | 8377087607
Β 
Call US-88OO1O2216 Call Girls In Mahipalpur Female Escort Service
Call US-88OO1O2216 Call Girls In Mahipalpur Female Escort ServiceCall US-88OO1O2216 Call Girls In Mahipalpur Female Escort Service
Call US-88OO1O2216 Call Girls In Mahipalpur Female Escort Service
Β 
8447779800, Low rate Call girls in Shivaji Enclave Delhi NCR
8447779800, Low rate Call girls in Shivaji Enclave Delhi NCR8447779800, Low rate Call girls in Shivaji Enclave Delhi NCR
8447779800, Low rate Call girls in Shivaji Enclave Delhi NCR
Β 
Kenya Coconut Production Presentation by Dr. Lalith Perera
Kenya Coconut Production Presentation by Dr. Lalith PereraKenya Coconut Production Presentation by Dr. Lalith Perera
Kenya Coconut Production Presentation by Dr. Lalith Perera
Β 
Buy gmail accounts.pdf Buy Old Gmail Accounts
Buy gmail accounts.pdf Buy Old Gmail AccountsBuy gmail accounts.pdf Buy Old Gmail Accounts
Buy gmail accounts.pdf Buy Old Gmail Accounts
Β 
Innovation Conference 5th March 2024.pdf
Innovation Conference 5th March 2024.pdfInnovation Conference 5th March 2024.pdf
Innovation Conference 5th March 2024.pdf
Β 
The-Ethical-issues-ghhhhhhhhjof-Byjus.pptx
The-Ethical-issues-ghhhhhhhhjof-Byjus.pptxThe-Ethical-issues-ghhhhhhhhjof-Byjus.pptx
The-Ethical-issues-ghhhhhhhhjof-Byjus.pptx
Β 
Call Us πŸ“²8800102216πŸ“ž Call Girls In DLF City Gurgaon
Call Us πŸ“²8800102216πŸ“ž Call Girls In DLF City GurgaonCall Us πŸ“²8800102216πŸ“ž Call Girls In DLF City Gurgaon
Call Us πŸ“²8800102216πŸ“ž Call Girls In DLF City Gurgaon
Β 
Unlocking the Future: Explore Web 3.0 Workshop to Start Earning Today!
Unlocking the Future: Explore Web 3.0 Workshop to Start Earning Today!Unlocking the Future: Explore Web 3.0 Workshop to Start Earning Today!
Unlocking the Future: Explore Web 3.0 Workshop to Start Earning Today!
Β 
Flow Your Strategy at Flight Levels Day 2024
Flow Your Strategy at Flight Levels Day 2024Flow Your Strategy at Flight Levels Day 2024
Flow Your Strategy at Flight Levels Day 2024
Β 
Pitch Deck Teardown: Geodesic.Life's $500k Pre-seed deck
Pitch Deck Teardown: Geodesic.Life's $500k Pre-seed deckPitch Deck Teardown: Geodesic.Life's $500k Pre-seed deck
Pitch Deck Teardown: Geodesic.Life's $500k Pre-seed deck
Β 
8447779800, Low rate Call girls in Uttam Nagar Delhi NCR
8447779800, Low rate Call girls in Uttam Nagar Delhi NCR8447779800, Low rate Call girls in Uttam Nagar Delhi NCR
8447779800, Low rate Call girls in Uttam Nagar Delhi NCR
Β 
Guide Complete Set of Residential Architectural Drawings PDF
Guide Complete Set of Residential Architectural Drawings PDFGuide Complete Set of Residential Architectural Drawings PDF
Guide Complete Set of Residential Architectural Drawings PDF
Β 
NewBase 19 April 2024 Energy News issue - 1717 by Khaled Al Awadi.pdf
NewBase  19 April  2024  Energy News issue - 1717 by Khaled Al Awadi.pdfNewBase  19 April  2024  Energy News issue - 1717 by Khaled Al Awadi.pdf
NewBase 19 April 2024 Energy News issue - 1717 by Khaled Al Awadi.pdf
Β 
Marketplace and Quality Assurance Presentation - Vincent Chirchir
Marketplace and Quality Assurance Presentation - Vincent ChirchirMarketplace and Quality Assurance Presentation - Vincent Chirchir
Marketplace and Quality Assurance Presentation - Vincent Chirchir
Β 
Kenya’s Coconut Value Chain by Gatsby Africa
Kenya’s Coconut Value Chain by Gatsby AfricaKenya’s Coconut Value Chain by Gatsby Africa
Kenya’s Coconut Value Chain by Gatsby Africa
Β 

Tips on how to improve the performance of your custom modules for high volumes deployment. Olivier Dony, OpenERP

  • 2. OpenERP can handle large volumes of transactions and large volumes of data out of the box!
  • 3. For example, each OpenERP Online Server hosts 1000+ databases without breaking a sweat!
  • 4. Many on-site customers have single server deployments with millions of rows: partners, emails, attachments, journal items, stock moves, workflow items, …
  • 5. What if performance is an issue? Get the right facts. Use the right tools.
  • 6. t @odony Agenda ● Architecture / Deployment / Sizing ● Measuring & Analyzing ● Common Problems ● Anti-patterns
  • 8. PostgreSQL is the real workhorse behind OpenERP, and it scales very well!
  • 9. t @odony OpenERP Cron Worker Deployment Architecture: single server, multi-process Rule of thumb: --workers=$((1+${CORES}*2)) OpenERP HTTP Worker OpenERP HTTP Worker OpenERP HTTP Worker OpenERP HTTP Worker PostgreSQL Requests
  • 10. t @odony OpenERP Cron Worker Deployment Architecture: multi-server, multi-process OpenERP HTTP Worker OpenERP HTTP Worker OpenERP HTTP Worker OpenERP HTTP Worker PostgreSQL Requests Server 3 Load Balancer OpenERP Cron Worker OpenERP HTTP Worker OpenERP HTTP Worker OpenERP HTTP Worker OpenERP HTTP Worker Server 2 Server 1
  • 11. t @odony Hardware Sizing ● Typical modern server machine ● 4/8/12 2+GHz cores ● 8-64 GB RAM ● Fast SATA/SAS/SSD disks ● Up to 100-200 active users (multi-process) ● Up to dozens of HTTP requests per second ● Up to 1000 β€œlight” users (average SaaS user) ● For official OpenERP 7.0 deployments with no customizations, and typical usage!
  • 12. For anything else, always perform proper load testing before going live in production! Then size accordingly...
  • 13. t @odony PostgreSQL Deployment tips ● Avoid deploying PostgreSQL on a VM ● If you must do it, fine-tune the VM for I/O! ● And always check out the basic PostgreSQL performance tuning, it's conservative by default http://wiki.postgresql.org/wiki/Tuning_Your_PostgreSQL_Server
  • 14. t @odony Agenda ● Architecture / Deployment / Sizing ● Measuring & Analyzing ● Common Problems ● Anti-patterns
  • 15. t @odony Monitor application response times ● You can't manage/improve what you can't measure ● Setup an automated monitoring of performance and response time... even if you have no performance problem! ● Suggested tool: munin ● Run OpenERP with –log-level=debug_rpc in prod! 2013-07-03 00:12:29,846 9663 DEBUG test openerp.netsvc.rpc.request: object.execute_kw time:0.031s mem: 763716k -> 763716k (diff: 0k)('test', 1, '*', 'sale.order', 'read', (...), {...})
  • 16. t @odony #!/bin/sh #%# family=manual #%# capabilities=autoconf suggest case $1 in autoconf) exit 0 ;; suggest) exit 0 ;; config) echo graph_category openerp echo graph_title openerp rpc request count echo graph_vlabel num requests/minute in last 5 minutes echo requests.label num requests exit 0 ;; esac # watch out for the time zone of the logs => using date -u for UTC timestamps result=$(tail -60000 /var/log/openerp.log | grep "object.execute_kw time" | awk "BEGIN{count=0} ($1 " " $2) >= "`date +'%F %H:%M:%S' -ud '5 min ago'`" { count+=1; } END{print count/5}") echo "requests.value ${result}" exit 0 Munin plugin: OpenERP requests/minute
  • 17. t @odony #!/bin/sh #%# family=manual #%# capabilities=autoconf suggest case $1 in config) echo graph_category openerp echo graph_title openerp rpc requests min/average response time echo graph_vlabel seconds echo graph_args --units-exponent -3 echo min.label min echo min.warning 1 echo min.critical 5 echo avg.label average echo avg.warning 1 echo avg.critical 5 exit 0 ;; esac # watch out for the time zone of the logs => using date -u for UTC timestamps result=$(tail -60000 /var/log/openerp.log | grep "object.execute_kw time" | awk "BEGIN{sum=0;count=0} ( $1 " " $2) >= "`date +'%F %H:%M:%S' -ud '5 min ago'`" {split($8,t,":");time=0+t[2];if (min=="") { min=time}; sum += time; count+=1; min=(time>min)?min:time } END{print min, sum/count}") echo -n "min.value " echo ${result} | cut -d" " -f1 echo -n "avg.value " echo ${result} | cut -d" " -f2 exit 0 Munin plugin: OpenERP min/avg response time
  • 18. t @odony #!/bin/sh #%# family=manual #%# capabilities=autoconf suggest case $1 in config) echo graph_category openerp echo graph_title openerp rpc requests max response time echo graph_vlabel seconds echo graph_args --units-exponent -3 echo max.label max echo max.warning 1 echo max.critical 5 exit 0 ;;.. esac # watch out for the time zone of the logs => using date -u for UTC timestamps.... result=$(tail -60000 /var/log/openerp.log | grep "object.execute_kw time" | awk "BEGIN{sum=0;count=0} ( $1 " " $2) >= "`date +'%F %H:%M:%S' -ud '85 min ago'`" {split($8,t,":");time=0+t[2]; sum += time; count+=1; max=(time<max)?max:time } END{print max}") echo "max.value ${result}" exit 0 Munin plugin: OpenERP max response time
  • 19. t @odony Monitor PostgreSQL ● postgresql.conf ● log_min_duration_statement = 50 ● Set to 50 or 100 in production ● Set to 0 to log all queries and execution times for a while ● Instagram gist to capture sample + analyze ● Analyze with pgBadger or pgFouine ● lc_messages = 'C'
  • 20. t @odony PostgreSQL Analysis ● Important PG statistic tables ● pg_stat_activity: near real-time view of transactions ● pg_locks: real-time view of existing locks ● pg_stat_user_tables: generic usage stats for all tables ● pg_statio_user_tables: generic I/O stats for all tables
  • 21. t @odony PostgreSQL Analysis: longest tables # SELECT schemaname || '.' || relname as table,n_live_tup as num_rows FROM pg_stat_user_tables ORDER BY n_live_tup DESC limit 10; β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ table β”‚ num_rows β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ public.stock_move β”‚ 179544 β”‚ β”‚ public.ir_translation β”‚ 134039 β”‚ β”‚ public.wkf_workitem β”‚ 97195 β”‚ β”‚ public.wkf_instance β”‚ 96973 β”‚ β”‚ public.procurement_order β”‚ 83077 β”‚ β”‚ public.ir_property β”‚ 69011 β”‚ β”‚ public.ir_model_data β”‚ 59532 β”‚ β”‚ public.stock_move_history_ids β”‚ 58942 β”‚ β”‚ public.mrp_production_move_ids β”‚ 49714 β”‚ β”‚ public.mrp_bom β”‚ 46258 β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  • 22. t @odony PostgreSQL Analysis: biggest tables # SELECT nspname || '.' || relname AS "table", pg_size_pretty(pg_total_relation_size(C.oid)) AS "total_size" FROM pg_class C LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace) WHERE nspname NOT IN ('pg_catalog', 'information_schema') AND C.relkind <> 'i' AND nspname !~ '^pg_toast' ORDER BY pg_total_relation_size(C.oid) DESC LIMIT 10; β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ table β”‚ total_size β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ public.stock_move β”‚ 525 MB β”‚ β”‚ public.wkf_workitem β”‚ 111 MB β”‚ β”‚ public.procurement_order β”‚ 80 MB β”‚ β”‚ public.stock_location β”‚ 63 MB β”‚ β”‚ public.ir_translation β”‚ 42 MB β”‚ β”‚ public.wkf_instance β”‚ 37 MB β”‚ β”‚ public.ir_model_data β”‚ 36 MB β”‚ β”‚ public.ir_property β”‚ 26 MB β”‚ β”‚ public.ir_attachment β”‚ 14 MB β”‚ β”‚ public.mrp_bom β”‚ 13 MB β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  • 23. t @odony PostgreSQL Analysis: biggest tables ● Consider using the file storage for the ir.attachment table ● Avoid storing files in the database ● Greatly reduces the time needed for DB backups and backup ● Very easy to rsync backups of DB dumps + filestore ● For 7.0 this setting is explained in this FAQ
  • 24. t @odony PostgreSQL Analysis: most read tables # SELECT schemaname || '.' || relname as table, heap_blks_read as disk_reads, heap_blks_hit as cache_reads, heap_blks_read + heap_blks_hit as total_reads from pg_statio_user_tables order by heap_blks_read + heap_blks_hit desc limit 15; β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ table β”‚ disk_reads β”‚ cache_reads β”‚ total_reads β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ public.stock_location β”‚ 53796 β”‚ 60926676388 β”‚ 60926730184 β”‚ β”‚ public.stock_move β”‚ 208763 β”‚ 9880525282 β”‚ 9880734045 β”‚ β”‚ public.stock_picking β”‚ 15772 β”‚ 4659569791 β”‚ 4659585563 β”‚ β”‚ public.procurement_order β”‚ 156139 β”‚ 1430660775 β”‚ 1430816914 β”‚ β”‚ public.stock_tracking β”‚ 2621 β”‚ 525023173 β”‚ 525025794 β”‚ β”‚ public.product_product β”‚ 11178 β”‚ 225774346 β”‚ 225785524 β”‚ β”‚ public.mrp_bom β”‚ 27198 β”‚ 225329643 β”‚ 225356841 β”‚ β”‚ public.ir_model_fields β”‚ 1632 β”‚ 203361139 β”‚ 203362771 β”‚ β”‚ public.stock_production_lot β”‚ 5918 β”‚ 127915614 β”‚ 127921532 β”‚ β”‚ public.res_users β”‚ 416 β”‚ 115506586 β”‚ 115507002 β”‚ β”‚ public.ir_model_access β”‚ 6382 β”‚ 104686364 β”‚ 104692746 β”‚ β”‚ public.mrp_production β”‚ 20829 β”‚ 101523983 β”‚ 101544812 β”‚ β”‚ public.product_template β”‚ 4566 β”‚ 76074699 β”‚ 76079265 β”‚ β”‚ public.product_uom β”‚ 18 β”‚ 70521126 β”‚ 70521144 β”‚ β”‚ public.wkf_workitem β”‚ 129166 β”‚ 67782919 β”‚ 67912085 β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  • 25. t @odony PostgreSQL Analysis: most updated/inserted/... # SELECT schemaname || '.' || relname as table, seq_scan,idx_scan,idx_tup_fetch+seq_tup_read lines_read_total, n_tup_ins as num_insert,n_tup_upd as num_update,n_tup_del as num_delete from pg_stat_user_tables order by n_tup_upd desc limit 10; β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ table β”‚ seq_scan β”‚ idx_scan β”‚ lines_read_total β”‚ num_insert β”‚ num_update β”‚ num_delete β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ public.stock_move β”‚ 1188095 β”‚ 1104711719 β”‚ 132030135782 β”‚ 208507 β”‚ 9556574 β”‚ 67298 β”‚ β”‚ public.procurement_order β”‚ 226774 β”‚ 22134417 β”‚ 11794090805 β”‚ 92064 β”‚ 6882666 β”‚ 27543 β”‚ β”‚ public.wkf_workitem β”‚ 373 β”‚ 17340039 β”‚ 29910699 β”‚ 1958392 β”‚ 3280141 β”‚ 1883794 β”‚ β”‚ public.stock_location β”‚ 41402098 β”‚ 166316501 β”‚ 516216409246 β”‚ 97 β”‚ 2215107 β”‚ 205 β”‚ β”‚ public.stock_picking β”‚ 297984 β”‚ 71732467 β”‚ 5671488265 β”‚ 9008 β”‚ 1000966 β”‚ 1954 β”‚ β”‚ public.stock_production_lot β”‚ 190934 β”‚ 28038527 β”‚ 1124560295 β”‚ 4318 β”‚ 722053 β”‚ 0 β”‚ β”‚ public.mrp_production β”‚ 270568 β”‚ 13550371 β”‚ 476534514 β”‚ 3816 β”‚ 495776 β”‚ 1883 β”‚ β”‚ public.sale_order_line β”‚ 30161 β”‚ 4757426 β”‚ 60019207 β”‚ 2077 β”‚ 479752 β”‚ 320 β”‚ β”‚ public.stock_tracking β”‚ 656404 β”‚ 97874788 β”‚ 5054452666 β”‚ 5914 β”‚ 404469 β”‚ 0 β”‚ β”‚ public.ir_cron β”‚ 246636 β”‚ 818 β”‚ 2467441 β”‚ 0 β”‚ 169904 β”‚ 0 β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  • 26. t @odony Useful VIEW to watch locked queries -- For PostgreSQL 9.1 CREATE VIEW monitor_blocked_queries AS SELECT pg_class.relname, waiter.pid as blocked_pid, substr(wait_act.current_query,1,30) as blocked_statement, age(now(),wait_act.query_start) as blocked_duration, holder.pid as blocking_pid, substr(hold_act.current_query,1,30) as blocking_statement, age(now(),hold_act.query_start) as blocking_duration, waiter.transactionid as xid, waiter.mode as wmode, waiter.virtualtransaction as wvxid, holder.mode as hmode, holder.virtualtransaction as hvxid FROM pg_locks holder join pg_locks waiter on ( holder.locktype = waiter.locktype and ( holder.database, holder.relation, holder.page, holder.tuple, holder.virtualxid, holder.transactionid, holder.classid, holder.objid, holder.objsubid ) IS NOT DISTINCT from ( waiter.database, waiter.relation, waiter.page, waiter.tuple, waiter.virtualxid, waiter.transactionid, waiter.classid, waiter.objid, waiter.objsubid )) JOIN pg_stat_activity hold_act ON (holder.pid=hold_act.procpid) JOIN pg_stat_activity wait_act ON (waiter.pid=wait_act.procpid) LEFT JOIN pg_class ON (holder.relation = pg_class.oid) WHERE wait_act.datname = 'eurogerm' AND holder.granted AND NOT waiter.granted ORDER BY blocked_duration DESC;
  • 27. t @odony Useful VIEW to watch locked queries # SELECT * FROM blocked_queries; relname | blocked_pid | blocked_statement | blocked_duration | blocking_pid | blocking_statement ---------+-------------+--------------------------------+------------------+--------------+------------------------- | 16504 | update "stock_tracking" set "s | 00:00:57.588357 | 16338 | <IDLE> in transaction | 16501 | update "stock_tracking" set "f | 00:00:55.144373 | 16504 | update "stock_tracking" (2 lignes) ... | blocking_statement | blocking_duration | xid | wmode | hmode | ... +--------------------------------+-------------------+----------+-----------+---------------| ... | <IDLE> in transaction | -00:00:00.004754 | 12630740 | ShareLock | ExclusiveLock | ... | update "stock_tracking" set "s | 00:00:57.588357 | 12630722 | ShareLock | ExclusiveLock |
  • 28. t @odony Useful tool for watching activity: pg_activity top-like command-line utility to watch queries: running, blocking, waiting β†’ pip install pg_activity Thanks to @cmorisse for this pointer! :-)
  • 29. t @odony Useful VIEW to watch Locks per transaction # – For PostgreSQL 9.1 # CREATE VIEW monitor_locks AS SELECT pg_stat_activity.procpid, pg_class.relname, pg_locks.locktype, pg_locks.transactionid, pg_locks.virtualxid, pg_locks.virtualtransaction, pg_locks.mode, pg_locks.granted, pg_stat_activity.usename, substr(pg_stat_activity.current_query,1,30) AS query, pg_stat_activity.query_start, age(now(),pg_stat_activity.query_start) AS duration FROM pg_stat_activity, pg_locks LEFT JOIN pg_class ON pg_locks.relation = pg_class.oid WHERE pg_locks.pid = pg_stat_activity.procpid AND pg_stat_activity.procpid != pg_backend_pid() ORDER BY pg_stat_activity.procpid, pg_locks.granted, pg_class.relname;
  • 30. t @odony Useful VIEW to watch Locks per transaction pid | relname | locktype | xid | virtualxid ------+-----------------------------------------------------------+------------------+----------+----------- 8597 | | transactionid | 12171567 | 11/164037 8597 | purchase_order_line_pkey | relation | | 11/164037 8597 | stock_location_location_id_index | relation | | 11/164037 8597 | stock_move_production_id_index | relation | | 11/164037 8597 | stock_move_production_id_index | relation | | 11/164037 8597 | stock_move_location_id_location_dest_id_product_id_state | relation | | 11/164037 8597 | multi_company_default | relation | | 11/164037 8597 | stock_picking_invoice_state_index | relation | | 11/164037 8597 | ir_model_access_group_id_index | relation | | 11/164037 8597 | purchase_order_line_date_planned_index | relation | | 11/164037 8597 | purchase_order_pkey | relation | | 11/164037 8597 | res_company | relation | | 11/164037 8597 | purchase_order_name_index | relation | | 11/164037 8597 | res_company | relation | | 11/164037 8597 | ir_sequence_pkey | relation | | 11/164037 8597 | ir_sequence_pkey | relation | | 11/164037 8597 | res_partner_company_id_index | relation | | 11/164037 8597 | product_product_have_pqcd_cde_index | relation | | 11/164037 8597 | stock_tracking | relation | | 11/164037 8597 | ir_translation_src_hash_idx | relation | | 11/164037 8597 | res_users | relation | | 11/164037 8597 | product_template_name_index | relation | | 11/164037 8597 | res_users | relation | | 11/164037 8597 | stock_move_tracking
  • 31. t @odony Useful VIEW to watch Locks per transaction | mode | granted | query | query_start | duration | +------------------+---------+--------------------------------+-------------------------------+------------------+ | AccessShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 | | AccessShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 | | AccessShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 | | AccessShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 | | RowExclusiveLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 | | AccessShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 | | AccessShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 | | AccessShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 | | AccessShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 | | AccessShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 | | AccessShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 | | AccessShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 | | AccessShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 | | RowShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 | | AccessShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 | | RowExclusiveLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 | | AccessShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 | | AccessShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 | | AccessShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 | | AccessShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 | | RowShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 | | AccessShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 | | AccessShareLock | t | <IDLE> in transaction | 2013-06-18 12:53:01.601039+02 | 00:00:00.278826 |
  • 32. t @odony Normal Values? ● Most RPC requests should be under 200ms ● Most SQL queries should be under 100ms ● One transaction = 100-300 heavyweight locks Find your own normal values via monitoring!
  • 33. t @odony Agenda ● Architecture / Deployment / Sizing ● Measuring & Analyzing ● Common Problems ● Anti-patterns
  • 34. t @odony Common Problems ● Stored functions ● Slow Queries/Views, Suboptimal domains ● Lock contention ● Custom locking mechanisms (queues, locks,...)
  • 35. t @odony Common Problems: Stored Functions ● Stored functional fields are triggers ● Store triggers can be: ● store = { 'trigger_model': (mapping_function, ['trigger_field1', 'trigger_field2'], priority) } ● store=True meaning: self._name (lambda s,c,u,ids,c: ids, None, 10)}β†’ ● Can be very expensive with wrong parameters or slow functions
  • 36. t @odony Common Problems: Slow Queries ● All SQL queries 500ms+ should be analyzed ● Use EXPLAIN ANALYZE to examine/measure you custom SQL queries and VIEWs ● Try to remove parts of the query until it's fast, then fix it ● Check cardinality of big JOINs ● Default domain evaluation strategy ● search([('picking_id.move_ids.partner_id', '!=', False)]) ● Implemented by combining β€œid IN (….)” parts ● Have a look at _auto_join in OpenERP 7.0 'move_ids': fields.one2many('stock.move', 'picking_id', string='Moves', _auto_join=True)
  • 37. t @odony Common Problems: Slow Queries ● No premature optimization: don't write SQL, use the ORM always during initial development ● If you detect a hot spot with load-tests, consider rewriting the inefficient parts in SQL ● But: ● Make sure you're not bypassing security mechanisms ● Don't create SQL injection vectors use query parameters,β†’ don't concatenate user input in your SQL strings.
  • 38. t @odony Common Problems: Lock Contention ● PostgreSQL guarantees transactional data integrity by taking heavy-weight locks β†’ monitor_locks ● Updating a record blocks all FK locks on it until the transaction is completed! ● This will change with PostgreSQL 9.3 :-) ● This is independent from the transaction isolation level (Repeatable Read/Serializable/...) β†’ Don't have long-running transactions! β†’ Avoid updating β€œmaster data” resources in them! (user, company, stock location, product, …)
  • 39. t @odony Common Problems: Custom Locking ● Any kind of manual locking/queuing mechanism is dangerous, especially in Python ● Python locks can cause deadlocks that cannot be detected and broken by the system! ● Avoid it, and if you must, use the database as lock ● That's what scheduled jobs (ir.cron) do: ● SELECT FOR UPDATE on the cron job row ● β†’ Automatic cleanup/release ● β†’ Scales well and works in multi-process!
  • 40. t @odony Agenda ● Architecture / Deployment / Sizing ● Measuring & Analyzing ● Common Problems ● Anti-patterns
  • 41. t @odony Avoid Anti-Patterns: Master the framework! ● Make sure you really understand the browse() mechanisms! ● Make sure you properly use the batch API ● Don't write SQL unless you have to, e.g for: ● Analysis views ● Hot spot functions, name_search(), computed_fields(), ...
  • 42. t @odony Anti-Patterns: what's wrong? browse() must be used on lists to benefit from its optimizations!
  • 43. t @odony Anti-Patterns: what's wrong now? browse() use is OK now, but the related field is dangerous and costly, going through a possibly very large o2m just to find a single product ID
  • 44. t @odony Anti-Patterns: what's wrong here? The trigger on stock.move is for all fields which means it will trigger for each change, while we only care about tracking_id here