PHP Performance 101:
so you need to use a database
Leon Fayer
@papa_fire
Who am I ?
• 20+ years development and operations of web applications
• currently Vice President at OmniTI
• can be found online:
• @papa_fire
• github:lfayer
• http://fayerplay.com
• https://joind.in/talk/view/11914
what it is about
databases & performance
what it’s not about
NoSQL MySQL
how database connection works
① establish connection
② send query
③ process query
④ send result
⑤ close connection
common database connection
$dbh = new DB(…);
$sth = $dbh->prepare($query);
$sth->execute();
$result = $sth->fetchAll();
$dbh = null;
common database connection
① var $dbh = new DB(…);
② var $sth = $dbh->prepare($query);
① $sth->execute();
② var $result = $sth->fetchAll();
③ $dbh = null;
① establish connection
① establish connection
⑤ close connection
and
problem
connection overhead
visual representation
①
①
①
⑤
⑤
⑤
short answer
persistent connections
short and helpful answer
persistent connections
avoid multiple connections
how it works (high level)
①
①
①
⑤
⑤
⑤
①
⑤
conclusion
reduce # of connections
② send query
most common problem
n+1
n+1
// get a list of items
$sth = $dbh->prepare("select item_id from items
where active = true");
$sth->execute();
$items = $sth->fetchAll();
// get properties for each items
foreach ($items as $i) {
$sth_prop = $dbh->prepare("select * from
item_properties where item_id = ?");
$sth_prop->execute($item);
$item_list[$i[‘item_id’]][‘props’] = $sth_prop->fetchAll();
$item_list[$i[‘item_id’]][‘id’] = $i[‘id’];
}
n+1 you don’t know about
// get a list of items
$items = get_active_item_ids();
// get properties for each items
foreach ($items as $i) {
$item = Item->new($i[‘item_id’])
$item_list[$i[‘item_id’][‘id’] = $item->item_id;
$item_list[$i[‘item_id’]][‘props’] = $item->properties();
}
easy solution
// get a list of items with properties
$sth = $dbh->prepare("select i. item_id, p.* from items i,
item_properties p
where i.item_id = p.item_id
and active = true");
$sth->execute();
$items = $sth->fetchAll();
// arrange object to your liking
foreach ($items as $i) {
$item_list[$i[‘item_id’]][‘props’] = $i;
$item_list[$i[‘item_id’]][‘id’] = $i[‘id’];
}
conclusion
limit number of queries
cool stuff
:BONUS:
Common Table Expressions
(CTEs)
* MySQL does not support CTEs
// create temp table naughty_users
// and get data from it
with naughty_users as (
select * from users where banned = 1
)
select userid, email from naughty_users;
even more cool
Writeable
Common Table Expressions
* Postgres 9.1+ only
multiple queries are required
// create user record
insert into users (name, email) values (?,?) returning
userid
// create address record
insert into addresses (userid, address, city, state,
zip) values (?,?,?,?,?) returning addressid
// track changes to user information
insert into user_history (userid, addressid, action)
values (?,?,?) returning historyid
or are they?
with userdata as (
insert into users (name, email) values (?,?)
returning userid
), addressdata as (
insert into addresses (userid, address, city, state, zip)
select userid,?,?,?,? from userdata
returning addressid
), historydata as (
insert into user_history (userid, addressid, action)
select userid, addressid,?
from userdata, addressdata
returning historyid
)
select userid, addressid, historyid
from userdata, addressdata, historydata;
why not use transactions?
• no complicated transaction code
• no complicated error handling code
• reduced query overhead
• better performance
find out more
For more details:
http://omniti.com/seeds/writable-ctes-improve-performance
③ process query
unpopular opinion
ORMs are evil
why?
1. machine-generated
2. object construction overhead
3. false sense of control
in one sentence
you have no idea how it works
timely tweet
conclusion
learn SQL
④ send results
may be shocking, but …
databases can do math
illustrating wrong
// get all orders
$sth = $dbh->prepare("select order_id, price from orders");
$sth->execute();
$orders= $sth->fetchAll();
//order by order_id
usort($orders, function ($a, $b) { if ($a['order_id'] == $b['order_id']) { return 0; }
return $a['order_id'] < $b['order_id'] ? -1 : 1; });
// get average $ for last 10 orders
$count = 1;
$total = 0;
$avg = 0;
foreach ($orders as $order) {
$total += $order[‘price’];
if ($count == 10) {
$avg = $total/$count;
break 1;
}
$count++;
}
vs right
// get average $ for last 10 orders
$sth = $dbh->prepare("select avg(price) as avg_price
from (select price from orders
order by order_id desc limit 10) ");
$sth->execute();
$orders= $sth->fetchAll();
$avg = $orders[‘avg_price’];
conclusion
learn SQL
other things to consider
1. cache is a wonderful thing
2. * is not your friend
3. EXPLAIN/ANALYZE are
Questions?

More Related Content

PDF
Developing applications for performance
PPTX
Database performance 101
PPTX
Wp query
KEY
テストデータどうしてますか?
PDF
Difference between mysql_fetch_array and mysql_fetch_assoc in PHP
PDF
Simple Ways To Be A Better Programmer (OSCON 2007)
PDF
How else can you write the code in PHP?
PPTX
Pitfalls to Avoid for Cascade Server Newbies by Lisa Hall
Developing applications for performance
Database performance 101
Wp query
テストデータどうしてますか?
Difference between mysql_fetch_array and mysql_fetch_assoc in PHP
Simple Ways To Be A Better Programmer (OSCON 2007)
How else can you write the code in PHP?
Pitfalls to Avoid for Cascade Server Newbies by Lisa Hall

What's hot (20)

PDF
[WLDN] Supercharging word press development in 2018
PPTX
You don’t know query - WordCamp UK Edinburgh 2012
PDF
WordCamp Portland 2018: PHP for WordPress
PPTX
Php functions
TXT
Manage catalog Configueation In Sharepoint PowerShell
PDF
Perl6 grammars
PPTX
16.mysql stored procedures in laravel
PDF
WordPress London 16 May 2012 - You don’t know query
PDF
PHPUnit でよりよくテストを書くために
PDF
Neatly folding-a-tree
PDF
Perl6 Regexen: Reduce the line noise in your code.
PDF
Intoduction to php restful web service
KEY
Introducing CakeEntity
PDF
Getting Creative with WordPress Queries
KEY
Introducing CakeEntity
ODP
Writing Maintainable Perl
KEY
Unit testing with zend framework PHPBenelux
PDF
Tips of CakePHP and MongoDB - Cakefest2011 ichikaway
PDF
Pim Elshoff "Final Class Aggregate"
[WLDN] Supercharging word press development in 2018
You don’t know query - WordCamp UK Edinburgh 2012
WordCamp Portland 2018: PHP for WordPress
Php functions
Manage catalog Configueation In Sharepoint PowerShell
Perl6 grammars
16.mysql stored procedures in laravel
WordPress London 16 May 2012 - You don’t know query
PHPUnit でよりよくテストを書くために
Neatly folding-a-tree
Perl6 Regexen: Reduce the line noise in your code.
Intoduction to php restful web service
Introducing CakeEntity
Getting Creative with WordPress Queries
Introducing CakeEntity
Writing Maintainable Perl
Unit testing with zend framework PHPBenelux
Tips of CakePHP and MongoDB - Cakefest2011 ichikaway
Pim Elshoff "Final Class Aggregate"
Ad

Similar to PHP performance 101: so you need to use a database (20)

PPTX
UNIT V (5).pptx
PPTX
Database Connectivity MYSQL by Dr.C.R.Dhivyaa Kongu Engineering College
ODP
Beyond php - it's not (just) about the code
PPTX
CHAPTER six DataBase Driven Websites.pptx
PPTX
Chapter 3.1.pptx
ODP
Beyond php - it's not (just) about the code
ODP
Beyond php it's not (just) about the code
KEY
Object Relational Mapping in PHP
PPTX
Why Your Database Queries Stink -SeaGl.org November 11th, 2016
PPT
Migrating from PHP 4 to PHP 5
PPTX
Drupal 8 database api
ODP
Beyond php - it's not (just) about the code
PPTX
working with PHP & DB's
ODP
Beyond PHP - It's not (just) about the code
PPSX
DIWE - Working with MySQL Databases
PDF
Beyond php - it's not (just) about the code
PPTX
MySQL with PHP
PPTX
PHP Database Programming Basics -- Northeast PHP
PPTX
3-Chapter-Edit.pptx debre tabour university
KEY
Hybrid MongoDB and RDBMS Applications
UNIT V (5).pptx
Database Connectivity MYSQL by Dr.C.R.Dhivyaa Kongu Engineering College
Beyond php - it's not (just) about the code
CHAPTER six DataBase Driven Websites.pptx
Chapter 3.1.pptx
Beyond php - it's not (just) about the code
Beyond php it's not (just) about the code
Object Relational Mapping in PHP
Why Your Database Queries Stink -SeaGl.org November 11th, 2016
Migrating from PHP 4 to PHP 5
Drupal 8 database api
Beyond php - it's not (just) about the code
working with PHP & DB's
Beyond PHP - It's not (just) about the code
DIWE - Working with MySQL Databases
Beyond php - it's not (just) about the code
MySQL with PHP
PHP Database Programming Basics -- Northeast PHP
3-Chapter-Edit.pptx debre tabour university
Hybrid MongoDB and RDBMS Applications
Ad

More from Leon Fayer (13)

PDF
Наследование legacy-систем и процессов, или Первые 90 дней в роли CTO
PDF
What kids can teach us about building effective teams
PDF
Как измерить успех
PDF
Bias in tech
PDF
Building the right architecture for you
PDF
Lost art of troubleshooting
PDF
Adventures in public speaking
PDF
BizOps and you
PDF
On call for developers
PDF
Production testing through monitoring
PPTX
What DevOps is Not
PDF
Breaking social dependency
PPTX
Improving DevOps through better monitoring
Наследование legacy-систем и процессов, или Первые 90 дней в роли CTO
What kids can teach us about building effective teams
Как измерить успех
Bias in tech
Building the right architecture for you
Lost art of troubleshooting
Adventures in public speaking
BizOps and you
On call for developers
Production testing through monitoring
What DevOps is Not
Breaking social dependency
Improving DevOps through better monitoring

Recently uploaded (20)

PDF
CloudStack 4.21: First Look Webinar slides
PDF
1 - Historical Antecedents, Social Consideration.pdf
PPTX
Benefits of Physical activity for teenagers.pptx
PPTX
Microsoft Excel 365/2024 Beginner's training
PDF
Developing a website for English-speaking practice to English as a foreign la...
PDF
How ambidextrous entrepreneurial leaders react to the artificial intelligence...
PDF
Produktkatalog für HOBO Datenlogger, Wetterstationen, Sensoren, Software und ...
PDF
A comparative study of natural language inference in Swahili using monolingua...
PDF
Consumable AI The What, Why & How for Small Teams.pdf
PPTX
Final SEM Unit 1 for mit wpu at pune .pptx
PDF
The influence of sentiment analysis in enhancing early warning system model f...
PPT
Geologic Time for studying geology for geologist
PDF
Abstractive summarization using multilingual text-to-text transfer transforme...
PPT
What is a Computer? Input Devices /output devices
PPT
Module 1.ppt Iot fundamentals and Architecture
PDF
UiPath Agentic Automation session 1: RPA to Agents
PPTX
Custom Battery Pack Design Considerations for Performance and Safety
PDF
ENT215_Completing-a-large-scale-migration-and-modernization-with-AWS.pdf
PDF
TrustArc Webinar - Click, Consent, Trust: Winning the Privacy Game
PPTX
Modernising the Digital Integration Hub
CloudStack 4.21: First Look Webinar slides
1 - Historical Antecedents, Social Consideration.pdf
Benefits of Physical activity for teenagers.pptx
Microsoft Excel 365/2024 Beginner's training
Developing a website for English-speaking practice to English as a foreign la...
How ambidextrous entrepreneurial leaders react to the artificial intelligence...
Produktkatalog für HOBO Datenlogger, Wetterstationen, Sensoren, Software und ...
A comparative study of natural language inference in Swahili using monolingua...
Consumable AI The What, Why & How for Small Teams.pdf
Final SEM Unit 1 for mit wpu at pune .pptx
The influence of sentiment analysis in enhancing early warning system model f...
Geologic Time for studying geology for geologist
Abstractive summarization using multilingual text-to-text transfer transforme...
What is a Computer? Input Devices /output devices
Module 1.ppt Iot fundamentals and Architecture
UiPath Agentic Automation session 1: RPA to Agents
Custom Battery Pack Design Considerations for Performance and Safety
ENT215_Completing-a-large-scale-migration-and-modernization-with-AWS.pdf
TrustArc Webinar - Click, Consent, Trust: Winning the Privacy Game
Modernising the Digital Integration Hub

PHP performance 101: so you need to use a database

  • 1. PHP Performance 101: so you need to use a database Leon Fayer @papa_fire
  • 2. Who am I ? • 20+ years development and operations of web applications • currently Vice President at OmniTI • can be found online: • @papa_fire • github:lfayer • http://fayerplay.com • https://joind.in/talk/view/11914
  • 3. what it is about databases & performance
  • 4. what it’s not about NoSQL MySQL
  • 5. how database connection works ① establish connection ② send query ③ process query ④ send result ⑤ close connection
  • 6. common database connection $dbh = new DB(…); $sth = $dbh->prepare($query); $sth->execute(); $result = $sth->fetchAll(); $dbh = null;
  • 7. common database connection ① var $dbh = new DB(…); ② var $sth = $dbh->prepare($query); ① $sth->execute(); ② var $result = $sth->fetchAll(); ③ $dbh = null;
  • 9. ① establish connection ⑤ close connection and
  • 13. short and helpful answer persistent connections avoid multiple connections
  • 14. how it works (high level) ① ① ① ⑤ ⑤ ⑤ ① ⑤
  • 15. conclusion reduce # of connections
  • 18. n+1 // get a list of items $sth = $dbh->prepare("select item_id from items where active = true"); $sth->execute(); $items = $sth->fetchAll(); // get properties for each items foreach ($items as $i) { $sth_prop = $dbh->prepare("select * from item_properties where item_id = ?"); $sth_prop->execute($item); $item_list[$i[‘item_id’]][‘props’] = $sth_prop->fetchAll(); $item_list[$i[‘item_id’]][‘id’] = $i[‘id’]; }
  • 19. n+1 you don’t know about // get a list of items $items = get_active_item_ids(); // get properties for each items foreach ($items as $i) { $item = Item->new($i[‘item_id’]) $item_list[$i[‘item_id’][‘id’] = $item->item_id; $item_list[$i[‘item_id’]][‘props’] = $item->properties(); }
  • 20. easy solution // get a list of items with properties $sth = $dbh->prepare("select i. item_id, p.* from items i, item_properties p where i.item_id = p.item_id and active = true"); $sth->execute(); $items = $sth->fetchAll(); // arrange object to your liking foreach ($items as $i) { $item_list[$i[‘item_id’]][‘props’] = $i; $item_list[$i[‘item_id’]][‘id’] = $i[‘id’]; }
  • 22. cool stuff :BONUS: Common Table Expressions (CTEs) * MySQL does not support CTEs
  • 23. // create temp table naughty_users // and get data from it with naughty_users as ( select * from users where banned = 1 ) select userid, email from naughty_users;
  • 24. even more cool Writeable Common Table Expressions * Postgres 9.1+ only
  • 25. multiple queries are required // create user record insert into users (name, email) values (?,?) returning userid // create address record insert into addresses (userid, address, city, state, zip) values (?,?,?,?,?) returning addressid // track changes to user information insert into user_history (userid, addressid, action) values (?,?,?) returning historyid
  • 26. or are they? with userdata as ( insert into users (name, email) values (?,?) returning userid ), addressdata as ( insert into addresses (userid, address, city, state, zip) select userid,?,?,?,? from userdata returning addressid ), historydata as ( insert into user_history (userid, addressid, action) select userid, addressid,? from userdata, addressdata returning historyid ) select userid, addressid, historyid from userdata, addressdata, historydata;
  • 27. why not use transactions? • no complicated transaction code • no complicated error handling code • reduced query overhead • better performance
  • 28. find out more For more details: http://omniti.com/seeds/writable-ctes-improve-performance
  • 31. why? 1. machine-generated 2. object construction overhead 3. false sense of control
  • 32. in one sentence you have no idea how it works
  • 36. may be shocking, but … databases can do math
  • 37. illustrating wrong // get all orders $sth = $dbh->prepare("select order_id, price from orders"); $sth->execute(); $orders= $sth->fetchAll(); //order by order_id usort($orders, function ($a, $b) { if ($a['order_id'] == $b['order_id']) { return 0; } return $a['order_id'] < $b['order_id'] ? -1 : 1; }); // get average $ for last 10 orders $count = 1; $total = 0; $avg = 0; foreach ($orders as $order) { $total += $order[‘price’]; if ($count == 10) { $avg = $total/$count; break 1; } $count++; }
  • 38. vs right // get average $ for last 10 orders $sth = $dbh->prepare("select avg(price) as avg_price from (select price from orders order by order_id desc limit 10) "); $sth->execute(); $orders= $sth->fetchAll(); $avg = $orders[‘avg_price’];
  • 40. other things to consider 1. cache is a wonderful thing 2. * is not your friend 3. EXPLAIN/ANALYZE are