SQL Antipatterns
SQL Antipatterns
Strike Back
Bill Karwin
1
1 Monday, April 20, 2009
Antipattern Categories
Database Design
Antipatterns
Database Creation
Antipatterns
Query
Antipatterns
Application
Antipatterns
CREATE TABLE BugsProducts (
bug_id INTEGER REFERENCES Bugs,
product VARCHAR(100) REFERENCES Products,
PRIMARY KEY (bug_id, product)
);
SELECT b.product, COUNT(*)
FROM BugsProducts AS b
GROUP BY b.product;
$dbHandle = new PDO(mysql:dbname=test);
$stmt = $dbHandle->prepare($sql);
$result = $stmt->fetchAll();
2
2 Monday, April 20, 2009
Antipattern Categories
Database Design
Antipatterns
Database Creation
Antipatterns
Query
Antipatterns
Application
Antipatterns
CREATE TABLE BugsProducts (
bug_id INTEGER REFERENCES Bugs,
product VARCHAR(100) REFERENCES Products,
PRIMARY KEY (bug_id, product)
);
SELECT b.product, COUNT(*)
FROM BugsProducts AS b
GROUP BY b.product;
$dbHandle = new PDO(mysql:dbname=test);
$stmt = $dbHandle->prepare($sql);
$result = $stmt->fetchAll();
3
3 Monday, April 20, 2009
Database Design Antipatterns
1. Metadata Tribbles
2. Entity-Attribute-Value
3. Polymorphic Associations
4. Naive Trees
4
4 Monday, April 20, 2009
Metadata Tribbles
5
I want these things off the ship. I dont care if it takes
every last man weve got, I want them off the ship.
James T. Kirk
5 Monday, April 20, 2009
Metadata Tribbles
Categories/subcategories
Bill of materials
Threaded discussions
49
49 Monday, April 20, 2009
Naive Trees
50
(1) Fran:
Whats the cause
of this bug?
(2) Ollie:
I think its a null
pointer.
(3) Fran:
No, I checked for
that.
(4) Kukla:
We need to
check valid input.
(5) Ollie:
Yes, thats a bug.
(6) Fran:
Yes, please add a
check.
(7) Kukla:
That xed it.
50 Monday, April 20, 2009
Naive Trees
Adjacency List
Adjacency List
Adjacency List
Adjacency List
Summary of Designs:
77
Design
Number of
Tables
Query
Child
Query
Subtree
Modify
Tree
Referential
Integrity
Adjacency List 1 Easy Hard Easy Yes
Path
Enumeration
1 Easy Easy Hard No
Nested Sets 1 Hard Easy Hard No
Closure Table 2 Easy Easy Easy Yes
77 Monday, April 20, 2009
Antipattern Categories
Database Design
Antipatterns
Database Creation
Antipatterns
Query
Antipatterns
Application
Antipatterns
CREATE TABLE BugsProducts (
bug_id INTEGER REFERENCES Bugs,
product VARCHAR(100) REFERENCES Products,
PRIMARY KEY (bug_id, product)
);
SELECT b.product, COUNT(*)
FROM BugsProducts AS b
GROUP BY b.product;
$dbHandle = new PDO(mysql:dbname=test);
$stmt = $dbHandle->prepare($sql);
$result = $stmt->fetchAll();
78
78 Monday, April 20, 2009
Database Creation Antipatterns
5. ENUM Antipattern
6. Rounding Errors
7. Indexes Are Magical
79
79 Monday, April 20, 2009
ENUM Antipattern
80
80 Monday, April 20, 2009
ENUM Antipattern
Especially money
FLOAT is inexact
SELECT hours FROM Bugs
WHERE bug_id = 1234;
!
3.3
SELECT hours * 1000000000 FROM Bugs
WHERE bug_id = 1234;
!
3299999952.3163
92
92 Monday, April 20, 2009
Rounding Errors
Inexact decimals
Antipatterns:
Longest-running.
Temporary table
Filesort
105 Monday, April 20, 2009
Indexes are Magical
ORDER BY criteria
MIN() / MAX()
WHERE conditions
MyISAM: key_buffer_size,
LOAD INDEX INTO CACHE
InnoDB: innodb_buffer_pool_size
108 Monday, April 20, 2009
Indexes are Magical
Analyze or rebuild
indexes, e.g. in MySQL:
ANALYZE TABLE
OPTIMIZE TABLE
109 Monday, April 20, 2009
Indexes are Magical
Antipatterns:
Antipatterns:
Solution:
Runs query
187
could invalidate
optimization plan
187 Monday, April 20, 2009
Parameter Facade
query
SELECT
FROM
WHERE
expr-list
*
simple-table
expr
bugs
1234
bug_id
= equality
supplied
value
188
188 Monday, April 20, 2009
Parameter Facade
query
SELECT
FROM
WHERE
expr-list
*
simple-table
expr
bugs
1234
or 1=1
bug_id
= equality
supplied
value
189
189 Monday, April 20, 2009
Parameter Facade
Example: IN predicate
SELECT * FROM bugs
WHERE bug_id IN ( ? );
SELECT * FROM bugs
WHERE bug_id IN ( ?, ?, ?, ? );
194
must supply
exactly four values
may supply
only one value
194 Monday, April 20, 2009
Parameter Facade
195
Scenario Value Interpolation Parameter
single value 1234 SELECT * FROM bugs
WHERE bug_id = $id;
SELECT * FROM bugs
WHERE bug_id = ?;
multiple values
1234, 3456, 5678
SELECT * FROM bugs
WHERE bug_id IN ($list);
SELECT * FROM bugs
WHERE bug_id IN ( ?, ?, ? );
column name bug_id SELECT * FROM bugs
WHERE $column = 1234; NO
table name bugs SELECT * FROM $table
WHERE bug_id = 1234; NO
other syntax bug_id = 1234 SELECT * FROM bugs
WHERE $expr; NO
195 Monday, April 20, 2009
Parameter Facade
Solution:
Auditing/logging confusion
204
SQL injection
204 Monday, April 20, 2009
Phantom Side Effects
Solution:
Antipatterns:
Ignoring exceptions:
$sql = SELECT * FROM Bugz;
$stmt = $pdo->query( $sql );
$rows = $stmt->fetchAll();
213
NOT
REACHED
throws PDOException
213 Monday, April 20, 2009
See No Evil
Troubleshooting code:
$sql = SELECT * FROM Bugs
WHERE summary LIKE \%
. $mysqli->quote( $feature )
. doesn\t work 50\% of the time!%\;
$result = $mysqli->query( $sql );
$rows = $result->fetchAll();
216
who wants to
read this!?
216 Monday, April 20, 2009
See No Evil
Functional testing
Documentation
Functional testing
Tables, Views,
Columns
Constraints
Triggers
Stored Procedures
Bootstrap Data
Queries
ORM Classes
222
Verify presence of
tables and views.
Verify absence of
tables, views, or
columns that you
dropped.
222 Monday, April 20, 2009
Diplomatic Immunity
Functional testing
Tables, Views,
Columns
Constraints
Triggers
Stored Procedures
Bootstrap Data
Queries
ORM Classes
223
Functional testing
Tables, Views,
Columns
Constraints
Triggers
Stored Procedures
Bootstrap Data
Queries
ORM Classes
224
Functional testing
Tables, Views,
Columns
Constraints
Triggers
Stored Procedures
Bootstrap Data
Queries
ORM Classes
225
Nevertheless, stored
procedures are useful,
e.g. solving tough
bottlenecks.
Functional testing
Tables, Views,
Columns
Constraints
Triggers
Stored Procedures
Bootstrap Data
Queries
ORM Classes
226
Functional testing
Tables, Views,
Columns
Constraints
Triggers
Stored Procedures
Bootstrap Data
Queries
ORM Classes
227
Application code is
laced with SQL queries.
Functional testing
Tables, Views,
Columns
Constraints
Triggers
Stored Procedures
Bootstrap Data
Queries
ORM Classes
228
Validation.
Transformation.
Monitoring.
Documentation
Entity Relation-
ship Diagram
Tables, Columns
Relationships
Views, Triggers
Stored Procedures
SQL Privileges
Application Code
229
229 Monday, April 20, 2009
Diplomatic Immunity
Documentation
Entity-Relationship
Diagram
Tables, Columns
Relationships
Views, Triggers
Stored Procedures
SQL Privileges
Application Code
230
Sample data.
Documentation
Entity-Relationship
Diagram
Tables, Columns
Relationships
Views, Triggers
Stored Procedures
SQL Privileges
Application Code
231
Documentation
Entity-Relationship
Diagram
Tables, Columns
Relationships
Views, Triggers
Stored Procedures
SQL Privileges
Application Code
232
Purpose of Views;
who uses them.
Usage of updatable
Views.
Validation
Transformation
Logging
232 Monday, April 20, 2009
Diplomatic Immunity
Documentation
Entity-Relationship
Diagram
Tables, Columns
Relationships
Views, Triggers
Stored Procedures
SQL Privileges
Application Code
233
Especially side-effects.
Encapsulation
Performance
Privileged access
233 Monday, April 20, 2009
Diplomatic Immunity
Documentation
Entity-Relationship
Diagram
Tables, Columns
Relationships
Views, Triggers
Stored Procedures
SQL Privileges
Application Code
234
Sets of privileges
(roles) used for
different scenarios.
Security measures.
234 Monday, April 20, 2009
Diplomatic Immunity
Documentation
Entity-Relationship
Diagram
Tables, Columns
Relationships
Views, Triggers
Stored Procedures
SQL Privileges
Application Code
235
Connection params.
Client options.
Driver versions.
Object-Relational
Mapping (ORM):
Validations, Logging,
Transformations.