检索数据
1、如果使用DISTINCT关键字,它必须直接放在列名的前面。不能部分使用DISTINCT,DISTINCT关键字应用于所有列而不仅是前置它的列
例如:SELECT DISTINCT vend_id告诉MySQL只返回不同(唯一)的vend_id行
2、带一个值的LIMIT总是从第一行开始,给出的数为返回的行数(例如LIMIT 5表示从第一行开始,读取五条数据)。带两个值的LIMIT可以指定从行号为第一个值的位置开始(例如LIMIT 5, 5表示从第六行开始,读取5条数据),检索出来的第一行为行0而不是行1。因此,LIMIT 1, 1将检索出第二行而不是第一行,LIMIT 4 OFFSET 3意为从行3开始取4行,就像LIMIT 3, 4一样
排序检索数据
1、对英文列用ORDER BY子句那么就会以字母顺序排序数据
2、为了实现按多个列排序,只要指定列名,列名之间用逗号分开即可
仅在多个行具有相同的prod_price 值时才对产品按prod_name进行排序。如果prod_price列中所有的值都是唯一的,则不会按prod_name排序。
3、数据排序不限于升序排序(从A到Z)。这只是默认的排序顺序,还可以使用ORDER BY子句以降序(从Z到A)顺序排序。为了进行降序排序, 必须指定DESC关键字
DESC关键字只应用到直接位于其前面的列名。在上例中,只对prod_price 列指定DESC ,对prod_name 列不指定。因此, prod_price列以降序排序,而prod_name列(在每个价格内)仍然按标准的升序排序。
4、在多个列上降序排序 如果想在多个列上进行降序排序,必须对每个列指定DESC关键字。
5、ORDER BY子句的位置 在给出ORDER BY子句时,应该保证它位于FROM子句之后。如果使用LIMIT,它必须位于ORDER BY 之后,否则将会产生错误
过滤数据
1、在同时使用ORDER BY和WHERE子句时,应该让ORDER BY位于WHERE之后,否则将会产生错误
2、 WHERE子句操作符
3、MySQL在执行匹配时默认不区分大小写
检查WHERE prod_name=‘fuses’语句,它返回prod_name的值为Fuses的一行。MySQL在执行匹配时默认不区分大小写,所以fuses与Fuses匹配。
4、NULL是无值(no value),它与字段包含0、空字符串或仅仅包含空格不同。SELECT语句有一个特殊的WHERE子句,可用来检查具有NULL值的列。 这个WHERE子句就是IS NULL子句
这条语句返回没有价格(空prod_price字段,不是价格为0)的所有产品
数据过滤
1、SQL(像多数语言一样)在处理OR操作符前,优先处理AND操作符。当SQL看到下述WHERE子句时,它理解为由供应商1003制造的任何价格为10美元(含)以上的产品,或者由供应商1002制造的任何产品。换句话说,由于AND在计算次序中优先级更高
2、IN在WHERE子句中用来指定要匹配值的清单的关键字,功能与OR相当,IN的最大优点是可以包含其他SELECT语句,使得能够更动态地建立WHERE子句
用通配符进行过滤
1、最常使用的通配符是百分号(%),%告诉MySQL接受jet之后的任意字符,不管它有多少字符。%匹配区分大小写 ,根据MySQL的配置方式,搜索可以是区分大小写的。如'jet%'与JetPack 1000将不匹配。
2、搜索模式'%anvil%'表示匹配任何位置包含文本anvil的值,而不论它之前或之后出现什么字符
3、重要的是要注意到,除了一个或多个字符外,%还能匹配0个字符。% 代表搜索模式中给定位置的0个、1个或多个字符
4、注意NULL ,虽然似乎%通配符可以匹配任何东西,但有一个例外,即NULL。即使是WHERE prod_name LIKE '%'也不能匹配用值NULL作为产品名的行。
5、下划线的用途与%一样,但下划线只匹配单个字符而不是多个字符。
6、正如所见,MySQL的通配符很有用。但这种功能是有代价的:通配符搜索的处理一般要比前面讨论的其他搜索所花时间更长。这里给出一些使用通配符要记住的技巧。
- 不要过度使用通配符。如果其他操作符能达到相同的目的,应该使用其他操作符。
- 在确实需要使用通配符时,除非绝对有必要,否则不要把它们用在搜索模式的开始处。把通配符置于搜索模式的开始处,搜索起来是最慢的。
-
仔细注意通配符的位置。如果放错地方,可能不会返回想要的数据。
用正则表达式进行搜索
1、下面的语句检索列prod_name包含 文本1000的所有行:
除关键字LIKE被REGEXP替代外,这条语句看上去非常像使用 LIKE的语句。它告诉MySQL:REGEXP后所跟的东西作为正则表达式(与文字正文1000匹配的一个正则表达式)处理。
这里使用了正则表达式.000。.是正则表达式语言中一个特殊 的字符。它表示匹配任意一个字符,因此,1000和2000都匹配且返回。
2、MySQL中的正则表达式匹配(自版本 3.23.4后)不区分大小写(即,大写和小写都匹配)。为区分大 小写,可使用BINARY关键字,如WHERE prod_name REGEXP BINARY 'JetPack .000'。
3、为搜索两个串之一(或者为这个串,或者为另一个串),使用|,如 下所示:
4、匹配任何单一字符。但是,如果你只想匹配特定的字符,怎么办?可通过指定一组用[和]括起来的字符来完成,如下所示:
5、集合可用来定义要匹配的一个或多个字符。例如,下面的集合将匹配数字0到9:
6、正则表达式语言由具有特定含义的特殊字符构成。我们已经看到.、[]、 |和-等,还有其他一些字符。请问,如果你需要匹配这些字符,应该怎么办呢?例如,如果要找出包含.字符的值,怎样搜索?请看下面的例子:
8、目前为止使用的所有正则表达式都试图匹配单次出现。如果存在一 个匹配,该行被检索出来,如果不存在,检索不出任何行。但有时需要 对匹配的数目进行更强的控制。例如,你可能需要寻找所有的数,不管 数中包含多少数字,或者你可能想寻找一个单词并且还能够适应一个尾 随的s(如果存在)等等。 这可以用表9-3列出的正则表达式重复元字符来完成。
9、目前为止的所有例子都是匹配一个串中任意位置的文本。为了匹配特定位置的文本,需要使用表9-4列出的定位符。
使用数据处理函数
1、Upper()将文本转换为大写
2、些常用的文本处理函数
SOUNDEX是一个将任何文 本串转换为描述其语音表示的字母数字模式的算法。SOUNDEX考虑了类似 的发音字符和音节,使得能对串进行发音比较而不是字母比较。虽然 SOUNDEX不是SQL概念,但MySQL(就像多数DBMS一样)都提供对SOUNDEX的支持
3、常用的日期和时间处理函数
首先需要注意的是MySQL使用的日期格式。无论你什么时候指定一个日期,不管是插入或更新表值还是用WHERE子句进行过滤,日期必须为 格式yyyy-mm-dd。因此,2005年9月1日,给出为2005-09-01。虽然其他的 日期格式可能也行,但这是首选的日期格式,因为它排除了多义性(如04/05/06是2006年5月4日或2006年4月5日或2004年5月6日或……)
4、常用的数值处理函数
汇总数据
1、AVG()通过对表中行数计数并计算特定列值之和,求得该列的平均 值。AVG()可用来返回所有列的平均值,也可以用来返回特定列或行的平均值。
- 使用COUNT(*)对表中行的数目进行计数,不管表列中包含的是空值(NULL)还是非空值。
- 使用COUNT(column)对特定列中具有值的行进行计数,忽略 NULL值。
3、虽然MAX()一般用来找出最大的 数值或日期值,但MySQL允许将它用来返回任意列中的最大 值,包括返回文本列中的最大值。在用于文本数据时,如果数 据按相应的列排序,则MAX()返回最后一行。MAX()函数忽略列值为NULL的行。
4、MIN()的功能正好与MAX()功能相反,它返回指定列的最小值。与 MAX()一样,MIN()要求指定列名,MIN()函数与MAX()函数类似, MySQL允许将它用来返回任意列中的最小值,包括返回文本 列中的最小值。在用于文本数据时,如果数据按相应的列排序, 则MIN()返回最前面的行。MIN()函数忽略列值为NULL的行。
5、ALL参数不需要指定,因为它是默认行为。如果 不指定DISTINCT,则假定为ALL。
6、如果指定列名,则DISTINCT只能用于COUNT()。DISTINCT 不能用于COUNT(*),因此不允许使用COUNT(DISTINCT), 否则会产生错误。类似地,DISTINCT必须使用列名,不能用 于计算或表达式
7、实际上SELECT 语句可根据需要包含多个聚集函数
分组数据
1、在具体使用GROUP BY子句前,需要知道一些重要的规定。
- GROUP BY子句可以包含任意数目的列。这使得能对分组进行嵌套, 为数据分组提供更细致的控制。
- 如果在GROUP BY子句中嵌套了分组,数据将在最后规定的分组上进行汇总。换句话说,在建立分组时,指定的所有列都一起计算 (所以不能从个别的列取回数据)。
- GROUP BY子句中列出的每个列都必须是检索列或有效的表达式 (但不能是聚集函数)。如果在SELECT中使用表达式,则必须在 GROUP BY子句中指定相同的表达式。不能使用别名。
- 除聚集计算语句外,SELECT语句中的每个列都必须在GROUP BY子句中给出。
- 如果分组列中具有NULL值,则NULL将作为一个分组返回。如果列中有多行NULL值,它们将分为一组。
- GROUP BY子句必须出现在WHERE子句之后,ORDER BY子句之前。
2、事实上,目前为止所 学过的所有类型的WHERE子句都可以用HAVING来替代。唯一的差别是WHERE过滤行,而HAVING过滤分组。所学过的有关WHERE的所有这些技术和选项都适用于HAVING。它们的句法是相同的,只是关键字有差别。
这里WHERE子句不起作用,因为过滤是基于分组聚集值而不是特定行值的。WHERE在数据分组前进行过滤,HAVING在数据分组后进行过滤。
3、GROUP BY和ORDER BY
一般在使用GROUP BY子句时,应该也给出ORDER BY子句。这是保证数据正确排序的唯一方法
4、SELECT语句中子句的顺序
使用子查询
1、在WHERE子句中使用子查询(如这里所示),应 该保证SELECT语句具有与WHERE子句中相同数目的列。通常, 子查询将返回单个列并且与单个列匹配,但如果需要也可以 使用多个列。
- 如果子查询中仅仅使用了自己定义的数据源, 这种查询是非相关子查询。 非相关子查询是独立于外部查询的子查询, 子查询总共执行一次, 执行完毕后将值传递给主查询。(子查询是一个单独的select语句,可以不依赖主查询单独运行。这种不依靠主查询,能够独立运行的子查询称为“非相关子查询”)
- 如果子查询中使用了主查询的数据源, 这种查询是相关子查询, 此时主查询的执行与相关子查询的执行相互依赖。
如何快速区分非相关子查询和相关子查询呢?最简单的办法的就是直接看子查询本身能否执行。比如执行下面的例子中的子查询:
mysql> select avg(score)
-> from choose
-> where student.student_no = choose.student_no and student_name = '张三';
会报错:1054 - Unknown column 'student.student_no' in 'where clause'
这样的查询语句构成的子查询便为相关子查询。
联结表
1、联结的创建非常简单
完全限定列名 在引用的列可能出现二义性时,必须使用完全限定列名(用一个点分隔的表名和列名)。如果引用一个没有用表名限制的具有二义性的列名,MySQL将返回错误。
2、笛卡儿积(cartesian product) 由没有联结条件的表关系返回的结果为笛卡儿积。检索出的行的数目将是第一个表中的行数乘以第二个表中的行数
3、应该保证所有联结都有WHERE子句,否则MySQL将返回比想要的数据多得多的数据。同理,应保证WHERE子句的正确性。不正确的过滤条件将导致MySQL返回不正确的数据。
4、基于两个表之间的相等测试。这种联结也称为内部联结。
5、ANSI SQL规范首选INNER JOIN语法。此外, 尽管使用WHERE子句定义联结的确比较简单,但是使用明确的 联结语法能够确保不会忘记联结条件,有时候这样做也能影响性能。
MySQL在运行时关联指定的每个表以处理联结。 这种处理可能是非常耗费资源的,因此应该仔细,不要联结 不必要的表。联结的表越多,性能下降越厉害。
创建高级联结
1、别名除了用于列名和计算字段外,SQL还允许给表名起别名,别名不仅能用于WHERE子句,它还可以用于SELECT的列表、ORDER BY子句 以及语句的其他部分。应该注意,表别名只在查询执行中使用。与列别名不一样,表别名 不返回到客户机。
2、自联结通常作为外部语句用来替代从相同表中检索数据时使用的子查询语句(简单说就是自己一个表用两次或者多次,自己联结自己)。虽然最终的结果是相同的,但有时候处理联结远比处理子查询快得多。
子查询
自联结
上面这个例子查询的结果是一样的
3、MySQL不支持简化字符*=和=*的使用,这两种操作符在其他DBMS中是很流行的
4、存在两种基本的外部联结形式:左外部联结(LEFT JOIN)和右外部联结(RIGHT JOIN)。它们之间的唯一差别是所关联的表的顺序不同。换句话说,左外部联结可通过颠倒FROM或WHERE子句中,表的顺序转换为右外部联结。因此,两种类型的外部联结可互换使用,而究竟使用哪一种纯粹是根据方便而定。
5、事实上,迄今为止我们建立的每个内部联结都是自然联结,很可能 我们永远都不会用到不是自然联结的内部联结。
内联结
自然联结
6、汇总一下关于联结及其使用的 某些要点。
- 注意所使用的联结类型。一般我们使用内部联结,但使用外部联结也是有效的。
- 保证使用正确的联结条件,否则将返回不正确的数据。
- 应该总是提供联结条件,否则会得出笛卡儿积。
- 在一个联结中可以包含多个表,甚至对于每个联结可以采用不同的联结类型。虽然这样做是合法的,一般也很有用,但应该在一 起测试它们前,分别测试每个联结。这将使故障排除更为简单。
7、驱动表与被驱动表
mysql中的表连接分为三种
1. 左连接 left join
左连接以左表为基础,查询出左表所有数据并且去匹配右表的数据,如果右表没有数据,则为空
2. 右连接 right join
右连接以右表为基础,查询出右表所有数据并且去匹配左表的数据,如果左表没有数据,则为空
3. 内连接 inner join
内连接会把左右表匹配的数据查询出来,不存在的数据直接忽略
驱动表与被驱动表的概念
驱动表是表连接中的基础表,也就是通过驱动表的数据结果集作为循环基础数据,然后一条一条的通过这个结果集的数据作为过滤条件到被驱动表中查询数据,然后合并
驱动与被驱动
左连接中左表是驱动表,右表是被驱动表
右连接中右表是驱动表,左表是被驱动表
内连接中表数据量较小的表会由mysql自动选择作为驱动表去驱动大表
有一个重点是,如果where条件存在的话 mysql会根据where实际条件进行驱动表的选择
sql优化中,一个比较重要的点就是要用小表驱动大表
原因
mysql表关联的算法,是通过驱动表去循环被驱动表,比如说,20w的大表和200条的小表,如果大表驱动,那么是20w条记录外循环,内循环200条去连接查找,需要通过20w次连接,如果小表驱动,那么是200条记录外循环,内循环20w条去连接查找,只需要通过200次连接就可以了,并且驱动表是不会使用索引的
组合查询
1、可用UNION操作符来组合数条SQL查询。利用UNION,可给出多条SELECT语句,将它们的结果组合成单个结果集。多数情况下,组合相同表的两个 查询完成的工作与具有多个WHERE子句条件的单条查询完成的 工作相同。换句话说,任何具有多个WHERE子句的SELECT语句都可以作为一个组合查询给出,在以下段落中可以看到这一点。 这两种技术在不同的查询中性能也不同。因此,应该试一下这 两种技术,以确定对特定的查询哪一种性能更好。
用Union(简单来说就是满足任意个select条件,但是注意两个select的字段是相同的)
用Where
- UNION必须由两条或两条以上的SELECT语句组成,语句之间用关键字UNION分隔(因此,如果组合4条SELECT语句,将要使用3个 UNION关键字)。
- UNION中的每个查询必须包含相同的列、表达式或聚集函数(不过各个列不需要以相同的次序列出)。
- 列数据类型必须兼容:类型不必完全相同,但必须是DBMS可以 隐含地转换的类型(例如,不同的数值类型或不同的日期类型)。
4、SELECT语句的输出用ORDER BY子句排序。在用UNION组合查询时,只 能使用一条ORDER BY子句,它必须出现在最后一条SELECT语句之后。对 于结果集,不存在用一种方式排序一部分,而又用另一种方式排序另一 部分的情况,因此不允许使用多条ORDER BY子句。
全文本搜索
此SELECT语句检索单个列note_text。由于WHERE子句,一个全 文本搜索被执行Match(note_text)指示MySQL针对指定的 列进行搜索,Against('rabbit')指定词rabbit作为搜索文本。由于有两行包含词rabbit,这两个行被返回
5、传递给 Match() 的值必须与 FULLTEXT()定义中的相同。如果指定多个列,则必须列出它们(而且次序正确)。
6、除非使用BINARY方式, 否则全文本搜索不区分大小写。
7、全文本搜索的一个重要部分就是对结果排序。具有较高等级的行先返回(因为这些行很
这里,在SELECT而不是WHERE子句中使用Match()和Against()。这 使所有行都被返回(因为没有WHERE子句)。Match()和Against() 用来建立一个计算列(别名为rank),此列包含全文本搜索计算出的等级值。等级由MySQL根据行中词的数目、唯一词的数目、整个索引中词的 总数以及包含该词的行的数目计算出来。正如所见,不包含词rabbit的 行等级为0(因此不被前一例子中的WHERE子句选择)。确实包含词rabbit 的两个行每行都有一个等级值,文本中词靠前的行的等级值比词靠后的 行的等级值高。
8、查询扩展用来设法放宽所返回的全文本搜索结果的范围。考虑下面 的情况。你想找出所有提到anvils的注释。只有一个注释包含词anvils, 但你还想找出可能与你的搜索有关的所有其他行,即使它们不包含词anvils。
首先进行一个简单的全文本搜索,没有查询扩展
下面是相同的搜索,这次使用查询扩展
此全文本搜索检索包含词heavy的所有行(有两行)。其中使用 了关键字IN BOOLEAN MODE,但实际上没有指定布尔操作符, 因此,其结果与没有指定布尔方式的结果相同
在布尔方式中,不按等级值降序排序返回的行。
10、邻近搜索是许多全文本搜索支持的一个特性,它能搜索相邻的词(在相同的句子中、相同的段落中或者在特定数目的词的部分中等等)。
插入数据
1、INSERT语句一般不会产生输出
2、不管使用哪种INSERT语法,都必须给出 VALUES的正确数目。如果不提供列名,则必须给每个表列提供 一个值。如果提供列名,则必须对每个列出的列给出一个值。 如果不这样,将产生一条错误消息,相应的行插入不成功。
3、如果表的定义允许,则可以在INSERT操作中省略某 些列。省略的列必须满足以下某个条件。
- 该列定义为允许NULL值(无值或空值)。
- 在表定义中给出默认值。这表示如果不给出值,将使用默认值。
5、INSERT可以插入一行到一个表中。但如果你想插入多个行怎么办?可以使用多条INSERT语句,甚至一次提交它们,每条语句用一个分号结束,如下所示:
或者,只要每条INSERT语句中的列名(和次序)相同,可以如下组 合各语句:
其中单条INSERT语句有多组值,每组值用一对圆括号括起来, 用逗号分隔。此技术可以提高数据库处理的性能,因 为MySQL用单条INSERT语句处理多个插入比使用多条INSERT 语句快
6、INSERT还存在 另一种形式,可以利用它将一条SELECT语句的结果插入表中。这就是所 谓的INSERT SELECT,顾名思义,它是由一条INSERT语句和一条SELECT 语句组成的
更新和删除数据
1、如果用UPDATE语句更新多行,并且在更新这些 行中的一行或多行时出一个现错误,则整个UPDATE操作被取消 (错误发生前更新的所有行被恢复到它们原来的值)。为即使是发 生错误,也继续进行更新,可使用IGNORE关键字,如下所示:
UPDATE IGNORE customers…
2、为了删除某个列的值,可设置它为NULL(假如表定义允许NULL值)。 如下进行:
其中NULL用来去除cust_email列中的值
3、在使用DELETE或者UPDATE语句时一定要注意细心(也就是要用Where语句来限制更新条件)。因为稍不注意,就会错误地删除/修改表中所有行。
4、DELETE不需要列名或通配符。DELETE删除整行而不是删除列。为了删除指定的列,请使用UPDATE语句。
5、DELETE语句从表中删除行,甚至是删除表中所有行。但是,DELETE不删除表本身。
6、下面是许多SQL程序员使用UPDATE或DELETE时所遵循的习惯。
- 除非确实打算更新和删除每一行,否则绝对不要使用不带WHERE 子句的UPDATE或DELETE语句。
- 保证每个表都有主键,尽可能 像WHERE子句那样使用它(可以指定各主键、多个值或值的范围)。
- 在对UPDATE或DELETE语句使用WHERE子句前,应该先用SELECT进行测试,保证它过滤的是正确的记录,以防编写的WHERE子句不正确。
- 使用强制实施引用完整性的数据库,这样MySQL将不允许删除具有与其他表相关联的数据的行。
-
MySQL 没有撤销( undo )按钮。应该非常小心地 使用UPDATE 和 DELETE ,否则你会发现自己更新或删除了错误的数据
创建和操纵表
1、为利用CREATE TABLE创建表,必须给出下列信息:
- 新表的名字,在关键字CREATE TABLE之后给出;
- 表列的名字和定义,用逗号分隔。
10、与大多数DBMS不一样,MySQL不允许使用函数作为默认值,它只支持常量。
11、如果省略ENGINE=语句,则 使用默认引擎(很可能是MyISAM),多数SQL语句都会默认使用它。但并不是所有语句都默认使用它,可以通过ENGINE=语句来指定引擎
以下是几个需要知道的引擎:
- InnoDB是一个可靠的事务处理引擎(参见第26章),它不支持全文本搜索;
- MEMORY在功能等同于MyISAM,但由于数据存储在内存(不是磁盘)中,速度很快(特别适合于临时表);
- MyISAM是一个性能极高的引擎,它支持全文本搜索,但不支持事务处理。
12、引擎类型可以混用。混用引擎类型有一个大缺陷。外键(用于强制实施引用完整性)不能跨引擎,即使用一个引擎的表不能引用具有使用不同引擎的表的外键。对事务没有要求通常用MyISAM 引擎。
13、为更新表定义,可使用ALTER TABLE语句。
ALTER TABLE的一种常见用途是定义外键。上面是给orderitems表增加一个fk_orderitems_orders表的外键约束,这个外键是order_num并且关联着orders
14、删除表(删除整个表而不是其内容)非常简单,使用DROP TABLE语 句即可:
15、使用RENAME TABLE语句可以重命名一个表:
管理事务处理
1、MyISAM和InnoDB是两种最常使用 的引擎。前者不支持明确的事务处理管理,而后者支持
2、事务处理是一种 机制,用来管理必须成批执行的MySQL操作,以保证数据库不包含不完整的操作结果。利用事务处理,可以保证一组操作不会中途停止,它们 或者作为整体执行,或者完全不执行(除非明确指示)。如果没有错误发 生,整组语句提交给(写到)数据库表。如果发生错误,则进行回退(撤 销)以恢复数据库到某个已知且安全的状态。
3、下面是关于事务处理需要知道的几个术语:
- 事务(transaction)指一组SQL语句;
- 回退(rollback)指撤销指定SQL语句的过程;
- 提交(commit)指将未存储的SQL语句结果写入数据库表;
- 保留点(savepoint)指事务处理中设置的临时占位符(plac-holder),你可以对它发布回退(与回退整个事务处理不同)。
4、MySQL使用下面的语句来标识事务的开始:
5、MySQL的ROLLBACK命令用来回退(撤销)MySQL语句,请看下面的语句:
9、默认的MySQL行为是自动提交所有更改。换句话说,任何 时候你执行一条MySQL语句,该语句实际上都是针对表执行的,而且所做的更改立即生效。为指示MySQL不自动提交更改,需要使用以下语句:
autocommit标志是针对每个连接而不是服务器的。
改善性能
- 首先,MySQL(与所有DBMS一样)具有特定的硬件建议。在学习和研究MySQL时,使用任何旧的计算机作为服务器都可以。但 对用于生产的服务器来说,应该坚持遵循这些硬件建议。
- 一般来说,关键的生产DBMS应该运行在自己的专用服务器上。
- MySQL是用一系列的默认设置预先配置的,从这些设置开始通常 是很好的。但过一段时间后你可能需要调整内存分配、缓冲区大小等。(为查看当前设置,可使用SHOW VARIABLES;和SHOW STATUS;)
- MySQL一个多用户多线程的DBMS,换言之,它经常同时执行多 个任务。如果这些任务中的某一个执行缓慢,则所有请求都会执 行缓慢。如果你遇到显著的性能不良,可使用SHOW PROCESSLIST 显示所有活动进程(以及它们的线程ID和执行时间)。你还可以用KILL命令终结某个特定的进程(使用这个命令需要作为管理员登录)。
-
总是有不止一种方法编写同一条 SELECT 语句。应该试验联结、并、子查询等,找出最佳的方法。
-
使用EXPLAIN语句让MySQL解释它将如何执行一条SELECT语句。
-
一般来说,存储过程执行得比一条一条地执行其中的各条 MySQL 语句快。
-
应该总是使用正确的数据类型。
-
决不要检索比需求还要多的数据。换言之,不要用 SELECT * (除 非你真正需要每个列)。
-
有的操作(包括 INSERT )支持一个可选的 DELAYED 关键字,如果 使用它,将把控制立即返回给调用程序,并且一旦有可能就实际 执行该操作。
-
在导入数据时,应该关闭自动提交。你可能还想删除索引(包括 FULLTEXT 索引),然后在导入完成后再重建它们。
-
必须索引数据库表以改善数据检索的性能。确定索引什么不是一 件微不足道的任务,需要分析使用的 SELECT 语句以找出重复的 WHERE 和 ORDER BY 子句。如果一个简单的 WHERE 子句返回结果所花 的时间太长,则可以断定其中使用的列(或几个列)就是需要索 引的对象。
-
你的 SELECT 语句中有一系列复杂的 OR 条件吗?通过使用多条 SELECT 语句和连接它们的 UNION 语句,你能看到极大的性能改 进。
-
索引改善数据检索的性能,但损害数据插入、删除和更新的性能。 如果你有一些表,它们收集数据且不经常被搜索,则在有必要之 前不要索引它们。(索引可根据需要添加和删除)
-
LIKE 很慢。一般来说,最好是使用 FULLTEXT 而不是 LIKE 。
-
数据库是不断变化的实体。一组优化良好的表一会儿后可能就面 目全非了。由于表的使用和内容的更改,理想的优化和配置也会 改变。
-
最重要的规则就是,每条规则在某些条件下都会被打破。