tags:

views:

143

answers:

5

Hi,

I am currently learning MySQL and am noticing a lot of different do's and don'ts.

Is there anywhere I can find the absolute list of best practices that you go by or learned from?

Thanks for your time.

A: 

Well, there won't be an absolute list of dos and donts as the goal posts keep moving. MySql moved on in leaps and bounds between versions 4 and 5, and some fairly essential bug fixes for MySql seem to be around the corner (I'm thinking of the issue surrounding the use of count(distinct col1) from ...).

Here are a couple of issues off the top of my head:

  1. don't rely on views to be able to use indexes on the underlying tables

http://forums.mysql.com/read.php?100,22967,66618#msg-66618

  1. The order of columns in indexes intended to be used by GROUP BY is important:

http://dev.mysql.com/doc/refman/5.1/en/group-by-optimization.html

  1. COUNT(DISTINCT) is slow:

http://www.delphifaq.com/faq/databases/mysql/f3095.shtml

  1. although there might be a bug fix a-coming....

http://bugs.mysql.com/bug.php?id=17865

Here are some other questions from this site you might find useful:

Database opimization

Database design with MySql

Finetuning tips

davek
A: 

DON'T WRITE YOUR SQL IN ALL CAPS, EVEN THOUGH THE OFFICIAL REFERENCE DOES IT. I MEAN, OK, IT MAKES IT PRETTY OBVIOUS TO DIFFERENTIATE BETWEEN IDENTIFIERS AND KEYWORDS. NO, WAIT, THAT'S WHY WE HAVE SYNTAX HIGHLIGHTING.

shylent
How MySQL-specific is this?
BalusC
TYPING IN ALL CAPS **DOESN'T** AFFECT THE PERFORMANCE OF THE QUERY.
OMG Ponies
+4  A: 

Do use InnoDB; don't use MyISAM.

(OK, OK, unless you absolutely have to, often due to fulltext matching not being available in InnoDB. Even then you're often better off putting the canonical data in InnoDB and the fulltext index on a separate MyISAM searchbait table, which you can then process for stemming.)

Do use BINARY columns when you want rigorous string matching, otherwise you get a case-insensitive comparison by default. Do set the collation correctly for your character set (best: UTF-8) or case-insensitive comparisons will behave strangely.

Do use ANSI SQL mode if you want your code to be portable. ANSI_QUOTES allows you to use standard double-quoted "identifier" (table, column, etc.) names to avoid reserved words; MySQL's default way of saying this is backquotes but they're non-standard and won't work elsewhere. If you can't control settings like this, omit any identifier quoting and try to avoid reserved words (which is annoying, as across the different databases there are many).

Do use your data access layer's MySQL string literal escaping or query parameterisation functions; don't try to create escaped literals yourself because the rules for them are a lot more complicated than you think and if you get it wrong you've got an SQL injection hole.

Don't rely on MySQL's behaviour of returning a particular row when you select columns that don't have a functional dependency on the GROUP BY column(s). This is an error in other databases and can easily hide bugs that will only pop up when the internal storage in the database changes, causing a different row to be returned.

SELECT productid, MIN(cost)
FROM products
GROUP BY productcategory  -- this doesn't do what you think
bobince
Great answer! I would, however, suggest avoiding using mysql's bizzare "feature", that allows you retrieve values from columns, that were not mentioned in group by clause. It simply makes no sense whatsoever. And by avoiding I mean "never ever doing it". Just pretend it produces an error.
shylent
Yes, that's my suggestion too, except when you're grouping by a row's primary key and retrieving other columns from that row. In that case they have a ‘functional dependency’ on the GROUP BY, so it's valid in ANSI SQL and works in other databases. You can of course add all those columns to the GROUP BY clause too, but it's a bit of a pain if there are loads of them.
bobince
A: 

Oh I need this list too .. joking. No. The problem is that whatever works with 1 MB database will never be good for 1 GB database, same applies to 1GB database vs 1TB database. etc.

RocketSurgeon
No, SOME things that work for a 1Mb database will still work for a 1 TB database. But in general, yes you are right.
MarkR
A: 

Do use SQL_MODE "Traditional".

SET SQL_MODE='TRADITIONAL'

Or put it in your my.cnf (even better, because you can't forget it; but ensure it gets deployed on to ALL instances including dev, test etc).

If you don't do this, inserting invalid values into columns will succeed anyway. This is not usually a Good Thing, as it may mean that you lose data.

It's important that it's turned on in dev as well as you'll spot those problems early.

MarkR