如何查看mysql数据库语句的create database语句

MySQL数据库创建、修改和删除表操作实例_西西软件资讯
西西软件下载最安全的下载网站、值得信赖的软件下载站!
→ MySQL数据库创建、修改和删除表操作实例
v4.3 英文绿色版
类型:数据库类大小:1.7M语言:英文 评分:6.6
其实对很多人来说对于SQL语句已经忘了很多,或者说是不懂很多,因为有图形操作软件,方便了大家,但是我们不能忘记最根本的东西,特别是一些细节上的东西,可能你用惯了Hibernate,不用写SQL语句,但是不是任何项目都要用到大框架的,如果不用,那你是不是就不会操作数据库了呢,所以我们最好还是熟悉一点好,对我们以后找工作和工作都有帮助。在说创建、修改和删除表前,我们还是要进行一个操作的简单说明:1.登陆数据库系统在命令行中登陆MySQL系统,输入一下内容:mysql -h localhost -u root -p很多人都知道这个,但是其中参数的具体表示什么我们还是要了解的,其中,“-h”参数指连接的主机名,所以后面是localhost;“-u”参数表示用户名,此处的用户名为root;“-p”参数表示用户的密码,按下Enter键后就显示“Enter password:”,输入密码即可登录进去了。2.创建数据库在创建数据库之前,我们可以查看已经存在的数据库:mysql& SHOW DATABASES;
+--------------------+
| Database
+--------------------+
| information_schema |
| community
| community_test
| performance_schema |
+--------------------+
8 rows in set (0.04 sec)创建数据库的格式:CREATE DATABASE 数据库名;示例:创建一个名为example的数据库mysql&
CREATE DATABASE
Query OK, 1 row affected (0.00 sec)
SHOW DATABASES;
+--------------------+
| Database
+--------------------+
| information_schema |
| community
| community_test
| performance_schema |
+--------------------+
9 rows in set (0.00 sec)3.删除数据库:格式:DROP DATABASE 数据库名;示例:删除example数据库mysql&
DROP DATABASE
Query OK, 0 rows affected (0.07 sec)
mysql& SHOW DATABASES;
+--------------------+
| Database
+--------------------+
| information_schema |
| community
| community_test
| performance_schema |
+--------------------+
8 rows in set (0.00 sec)4.数据库存储引擎存储引擎就是指表的类型,数据库存储引擎决定了表在计算机的存储方式。MySQL中查询存储引擎的类型命令:SHOW ENGINES;mysql& SHOW ENGINES;
+--------------------+---------+------------------------------------------------
----------------+--------------+------+------------+
| Support | Comment
| Transactions | XA
| Savepoints |
+--------------------+---------+------------------------------------------------
----------------+--------------+------+------------+
| FEDERATED
| Federated MySQL storage engine
| NULL | NULL
| MRG_MYISAM
| Collection of identical MyISAM tables
| MyISAM storage engine
| BLACKHOLE
| /dev/null storage engine (anything you write to
it disappears) | NO
| CSV storage engine
| Hash based, stored in memory, useful for tempor
ary tables
| Archive storage engine
| DEFAULT | Supports transactions, row-level locking, and f
oreign keys
| PERFORMANCE_SCHEMA | YES
| Performance Schema
+--------------------+---------+------------------------------------------------
----------------+--------------+------+------------+
9 rows in set (0.00 sec)查询结果中,Engine参数指存储引擎名称;Support参数说明MySQL是否支持该类型引擎;Comment参数表示对该引擎的评论;Transaction参数表示是否支持事务处理;XA参数表示是否分布式交易处理的XA规范;Savepoints参数表示是否支持保存点,以方便事务的回滚操作;由上面我们看到InnoDB存储引擎是default的,也就是数据库默认的存储引擎,下面我们简单介绍一下InnoDB。InnoDB是MySQL的一种存储引擎,InnoDB给MySQL提供了事务、回滚、崩溃修复能力和多版本并发控制的事务安全。InnoDB是MySQL上第一个提供外键约束的表引擎,而且对事务处理的能力,也是其他存储引擎不能比拟的。不过这种引擎的缺点就是读写效率稍差,占用的数据空间相对比较大。下面就是正式的内容:创建表:1)创建表的形式:CREATE TABLE 表名 (
属性名 数据类型 [完整约束条件],
属性名 数据类型 [完整约束条件],
属性名 数据类型 [完整约束条件]
);如果你很急的登陆进去就创建表,恭喜你,你会出现“No database selected”的错误,因为你没有告诉别人你要选择在哪个数据库创建表,所以在创建之前要选择数据库,格式:USE 数据库名;示例创建一个student表:mysql&
Database changed
mysql& CREATE TABLE student (
-& id int,
-& name varchar(20)
Query OK, 0 rows affected (0.09 sec)上面创建表的时候涉及到一个完整性约束条件,下面就列出一个完整性约束条件表:约束条件说明PRIMARY&KEY&标识该属性为该表的主键,可以唯一的标识对应的元组FOREIGN KEY&标识该属性为该表的外键,是与之联系某表的主键&NOT NULL&标识该属性不能为空UNIQUE&标识该属性的值是唯一的AUTO_INCREMENT&标识该属性的值是自动增加,这是MySQL的SQL语句的特色&DEFAULT为该属性设置默认值下面讲解一下上面完整性约束条件的应用:2)设置表的主键单字段主键格式:属性名 数据类型 PRIMARY KEY示例:mysql&
CREATE TABLE student1 (
-& id int PRIMARY KEY,
-& name varchar(20)
Query OK, 0 rows affected (0.06 sec)多字段主键格式:PRIMARY KEY(属性名1,属性名2....属性名n)示例:mysql& CREATE TABLE student2 (
-& id int,
-& stu_id int,
-& name varchar(20),
-& PRIMARY KEY(id,stu_id)
Query OK, 0 rows affected (0.00 sec)3)设置表的外键格式:CONSTRAINT 外键别名 FOREIGN KEY(属性1,属性2,....属性n) REFERENCES 表名(属性1',属性2',...属性n')示例:mysql& CREATE TABLE teacher (
-& id int PRIMARY KEY,
-& stu_id int,
-& name varchar(20),
-& CONSTRAINT STUID FOREIGN KEY(stu_id) REFERENCES student1(id)
Query OK, 0 rows affected (0.00 sec)4)设置表的非空约束简单的说就是不让这个属性的值为空,不填的话就会报错格式:属性名 数据类型 NOT NULL5)设置表的唯一性约束就是这个属性的值是不能重复的格式:属性名 数据类型 UNIQUE6)设置表的属性值自动增加AUTO_INCREMENT约束的字段可以是任何整数类型(TINYINT、SMALLINT、INT和BIGINT),在默认的情况下,该字段的值是从1开始自增格式:属性名 数据类型 AUTO_INCREMENT7)设置表的属性的默认值格式:属性名 数据类型 DEFAULT 默认值下面对4-7进行综合示例:mysql& CREATE TABLE student3 (
-& id int PRIMARY KEY AUTO_INCREMENT,
-& teacher_id int UNIQUE,
-& name varchar(20) NOT NULL,
-& sex varchar(10) DEFAULT 'male'
Query OK, 0 rows affected (0.01 sec)查看表结构查看表基本结构语句DESCRIBE格式:DESCRIBE 表名;通过查看表的结构,就很明确的对表进行解读,而且可以查看一下自己创建的表有没错误,这个SQL语句必须会用啊示例:mysql& desc student3;
+------------+-------------+------+-----+---------+----------------+
| Null | Key | Default | Extra
+------------+-------------+------+-----+---------+----------------+
| PRI | NULL
| auto_increment |
| teacher_id | int(11)
| UNI | NULL
| varchar(20) | NO
| varchar(10) | YES
+------------+-------------+------+-----+---------+----------------+
4 rows in set (0.01 sec)查看表详细结构语句SHOW CREATE TABLE通过这个SQL语句可以查看表的详细定义,除了字段名、字段的数据类型、约束条件外,还可以查看表的默认存储引擎和字符编码格式:SHOW CREATE TABLE 表名;示例:mysql& SHOW CREATE TABLE student3;
+----------+-----------------------------------
-----------------------------------------------
-----------------------------------------------
---------------------------------------------+
| Create Table
+----------+-----------------------------------
-----------------------------------------------
-----------------------------------------------
---------------------------------------------+
| student3 | CREATE TABLE `student3` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`teacher_id` int(11) DEFAULT NULL,
`name` varchar(20) NOT NULL,
`sex` varchar(10) DEFAULT 'male',
PRIMARY KEY (`id`),
UNIQUE KEY `teacher_id` (`teacher_id`)
) ENGINE=InnoDB DEFAULT CHARSET=gb2312 |
+----------+-----------------------------------
-----------------------------------------------
-----------------------------------------------
---------------------------------------------+
1 row in set (0.00 sec)修改表:1)修改表名表名可以在一个数据库中唯一的确定一张表。格式:ALTER TABLE 旧表名 RENAME 新表名;示例:mysql& ALTER TABLE student RENAME student4;
Query OK, 0 rows affected (0.11 sec)
mysql& DESCRIBE
ERROR 1146 (42S02): Table 'example.student' doesn't exist由上面可以看出,改名后的表已经不存在了。2)修改字段的数据类型格式:ALTER TABLE 表名 MODIFY 属性名 数据类型;示例:mysql& DESCRIBE student1;
+-------+-------------+------+-----+---------+-------+
| Field | Type
| Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| PRI | NULL
| varchar(20) | YES
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.08 sec)
mysql& ALTER TABLE student1 MODIFY name varchar(30);
Query OK, 0 rows affected (0.06 sec)
Records: 0
Duplicates: 0
Warnings: 0
mysql& DESCRIBE student1;
+-------+-------------+------+-----+---------+-------+
| Field | Type
| Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| PRI | NULL
| varchar(30) | YES
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.01 sec)3)修改字段名:格式:ALTER TABLE 表名 CHANGE 旧属性名 新属性名 新数据类型;示例:mysql& DESCRIBE student1;
+-------+-------------+------+-----+---------+-------+
| Field | Type
| Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| PRI | NULL
| varchar(30) | YES
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
mysql& ALTER TABLE student1 CHANGE name stu_name varchar(40);
Query OK, 0 rows affected (0.01 sec)
Records: 0
Duplicates: 0
Warnings: 0
mysql& DESCRIBE student1;
+----------+-------------+------+-----+---------+-------+
| Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| PRI | NULL
| stu_name | varchar(40) | YES
+----------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)这里我修改的字段名的同时也修改了数据类型了,如果你不想修改数据类型的话就按照原来的写就行了。4)增加字段格式:ALTER TABLE 表名 ADD 属性名1 数据类型 [完整性约束条件] [FIRST | AFTER 属性名2];其中,“属性名1”参数指需要增加的字段的名称;“FIRST”参数是可选参数,其作用是将新增字段设置为表的第一个字段;“AFTER”参数也是可选的参数,其作用是将新增字段添加到“属性名2”后面;“属性名2”当然就是指表中已经有的字段示例:mysql& DESCRIBE student1;
+----------+-------------+------+-----+---------+-------+
| Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| PRI | NULL
| stu_name | varchar(40) | YES
+----------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
mysql& ALTER TABLE student1 ADD teacher_name varchar(20) NOT NULL AFTER
Query OK, 0 rows affected (0.01 sec)
Records: 0
Duplicates: 0
Warnings: 0
mysql& DESCRIBE student1;
+--------------+-------------+------+-----+---------+-------+
| Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+-------+
| PRI | NULL
| teacher_name | varchar(20) | NO
| stu_name
| varchar(40) | YES
+--------------+-------------+------+-----+---------+-------+
3 rows in set (0.01 sec)5)删除字段格式:ALTER TABLE 表名 DROP 属性名;示例:mysql& DESCRIBE student1;
+--------------+-------------+------+-----+---------+-------+
| Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+-------+
| PRI | NULL
| teacher_name | varchar(20) | NO
| stu_name
| varchar(40) | YES
+--------------+-------------+------+-----+---------+-------+
3 rows in set (0.01 sec)
mysql& ALTER TABLE student1 DROP teacher_
Query OK, 0 rows affected (0.01 sec)
Records: 0
Duplicates: 0
Warnings: 0
mysql& DESCRIBE student1;
+----------+-------------+------+-----+---------+-------+
| Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| PRI | NULL
| stu_name | varchar(40) | YES
+----------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)6)更改表的存储引擎格式:ALTER TABLE 表名 ENGINE = 存储引擎名;示例:mysql& SHOW CREATE TABLE student2;
+----------+----------------------------------------
----------------------------------------------------
----------------------------------------------------
| Create Table
+----------+----------------------------------------
----------------------------------------------------
----------------------------------------------------
| student2 | CREATE TABLE `student2` (
`id` int(11) NOT NULL DEFAULT '0',
`stu_id` int(11) NOT NULL DEFAULT '0',
`name` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`,`stu_id`)
) ENGINE=InnoDB DEFAULT CHARSET=gb2312 |
+----------+----------------------------------------
----------------------------------------------------
----------------------------------------------------
1 row in set (0.05 sec)
mysql& ALTER TABLE student2 ENGINE = MYISAM;
Query OK, 0 rows affected (0.02 sec)
Records: 0
Duplicates: 0
Warnings: 0
mysql& SHOW CREATE TABLE student2;
+----------+----------------------------------------
----------------------------------------------------
----------------------------------------------------
| Create Table
+----------+----------------------------------------
----------------------------------------------------
----------------------------------------------------
| student2 | CREATE TABLE `student2` (
`id` int(11) NOT NULL DEFAULT '0',
`stu_id` int(11) NOT NULL DEFAULT '0',
`name` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`,`stu_id`)
) ENGINE=MyISAM DEFAULT CHARSET=gb2312 |
+----------+----------------------------------------
----------------------------------------------------
----------------------------------------------------
1 row in set (0.00 sec)7)删除表的外键约束格式:ALTER TABLE 表名 DROP FOREIGN KEY 外键别名;示例:mysql& SHOW CREATE TABLE
+---------+------------------------------------------------
-----------------------------------------------------------
-----------------------------------------------------------
--------------------------------------------------+
| Create Table
+---------+------------------------------------------------
-----------------------------------------------------------
-----------------------------------------------------------
--------------------------------------------------+
| teacher | CREATE TABLE `teacher` (
`id` int(11) NOT NULL,
`stu_id` int(11) DEFAULT NULL,
`name` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `STUID` (`stu_id`),
CONSTRAINT `STUID` FOREIGN KEY (`stu_id`) REFERENCES `stu
) ENGINE=InnoDB DEFAULT CHARSET=gb2312 |
+---------+------------------------------------------------
-----------------------------------------------------------
-----------------------------------------------------------
--------------------------------------------------+
1 row in set (0.08 sec)
mysql& ALTER TABLE teacher DROP FOREIGN KEY STUID;
Query OK, 0 rows affected (0.04 sec)
Records: 0
Duplicates: 0
Warnings: 0
mysql& SHOW CREATE TABLE
+---------+------------------------------------------------
-----------------------------------------------------------
--------------------------------------------------------+
| Create Table
+---------+------------------------------------------------
-----------------------------------------------------------
--------------------------------------------------------+
| teacher | CREATE TABLE `teacher` (
`id` int(11) NOT NULL,
`stu_id` int(11) DEFAULT NULL,
`name` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `STUID` (`stu_id`)
) ENGINE=InnoDB DEFAULT CHARSET=gb2312 |
+---------+------------------------------------------------
-----------------------------------------------------------
--------------------------------------------------------+
1 row in set (0.00 sec)删除表:格式:DROP TABLE 表名;删除没有被关联的普通表:直接上面的SQL语句就行了删除被其他表关联的父表:方法一:先删除子表,在删除父表方法二:删除父表的外键约束(上面有介绍),再删该表
08-2008-1508-1008-0908-0607-2607-1107-1106-1906-19
阅读本文后您有什么感想? 已有23人给出评价!
名称大小下载SQL――MYSQL查询语句大全
您当前位置: &
[ 所属分类
作者 红领巾 ]
1:使用SHOW语句找出在服务器上当前存在什么数据库:& SHOW DATABASES;2:2、创建一个数据库MYSQLDATAmysql& CREATE DATABASE MYSQLDATA;3:选择你所创建的数据库mysql& USE MYSQLDATA; (按回车键出现Database changed 时说明操作成功!)4:查看现在的数据库中存在什么表mysql& SHOW TABLES;5:创建一个数据库表mysql& CREATE TABLE MYTABLE (name VARCHAR(20), sexCHAR(1));6:显示表的结构:mysql& DESCRIBE MYTABLE;7:往表中加入记录mysql& insert into MYTABLE values (”hyq”,”M”);8:用文本方式将数据装入数据库表中(例如D:/mysql.txt)mysql& LOAD DATA LOCAL INFILE “D:/mysql.txt” INTOTABLE MYTABLE;9:导入.sql文件命令(例如D:/mysql.sql)mysql&mysql&source d:/mysql.10:删除表mysql&drop TABLE MYTABLE;11:清空表mysql&delete from MYTABLE;12:更新表中数据mysql&update MYTABLE set sex=”f” where name=’hyq’;
本文数据库(mssql)相关术语:熊片数据库 mssql数据库 oracle数据库 pubmed数据库 access数据库 万方数据库
转载请注明本文标题:本站链接:
分享请点击:
1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
把一件件小事做好,最后就做成了大事。
手机客户端
,专注代码审计及安全周边编程,转载请注明出处:http://www.codesec.net
转载文章如有侵权,请邮件 admin[at]codesec.nethttp://www.tngou.net/blog/mysql []
今日访问:0()
昨日访问:0
本周访问:0
本月访问:0
所有访问:0
来快速修复所有的数据库或者特定的数据库;
方法:进入Mysql的Bin目录:C:\Program&Files\MySQL\MySQL&Server&\bin
运行:mysqlcheck&-A&-o&-r&-uroot&-p123
注意,将123改成你自己的root用户密码
& 普通MySQL运行,数据量和访问量不大的话,是足够快的,但是当数据量和访问量剧增的时候,那么就会明显发现MySQL很慢,甚至down掉,那么就要考虑优化我们的MySQL了。&&&&& 优化无非是从三个角度入手:第一个是从硬件,增加硬件,增加服务器第二个就是对我们的MySQL服务器进行优化,增加缓存大小,开多端口,读写分开第三个就是我们的应用优化,建立索引,优化SQL查询语句,建立缓存等等&&&&&
我就简单的说说SQL查询语句的优化。因为如果我们Web服务器比数据库服务器多或者性能优良的话,我们完全可以把数据库的压力转嫁到Web服务器上,因
为如果单台MySQL,或者 Master/Slave
架构的数据库服务器都负担比较重,那么就可以考虑把MySQL的运算放到Web服务器上去进行。当然了,如果你Web服务器比数据库服务器差,那就把压力
放在数据库服务器上吧,呵呵。&&&&&
如果是把MySQL服务器的压力放在Web服务器上,那么很多运算就需要我们的程序去执行,比如Web程序中全部交给PHP脚本去处理数据。单台
MySQL服务器,查询、更新、插入、删除都在一台服务器上的话,访问量一大,你会明显发现锁表现象,当对一个表进行更新删除操作的时候,就会拒绝其他操
作,这样就会导致锁表,解决这个问题最简单直接的办法就是拿两台MySQL服务器,一台负责查询(select)操作,另外一台负责更改
(update/delete/insert),然后进行同步,这样能够避免锁表,如果服务器更多,那么就更好处理了,可以采用分布式数据库架构和数据的
散列存储,下面我们会简单说一下。&一、SQL的优化和注意事项&&&&& 现在我们假设我们只有一台MySQL服务器,所有的select/update/insert/delete操作都是在这上面进行的,我们同时有三台Web服务器,通过DNS轮巡来访问,那么我们如何进行我们应用程序和SQL的优化。&&&&& 1. Where条件&&&&& 在查询中,WHERE条件也是一个比较重要的因素,尽量少并且是合理的where条件是很重要的,在写每一个where条件的时候都要仔细考虑,尽量在多个条件的时候,把会提取尽量少数据量的条件放在前面,这样就会减少后一个where条件的查询时间。&&&&& 有时候一些where条件会导致索引无效,当使用了Mysql函数的时候,索引将无效,比如:select * from tbl1 where left(name, 4) = ‘hylr’,那么这时候索引无效,还有就是使用LIKE进
行搜索匹配的时候,这样的语句索引是无效的:select * from tbl1 where name like
‘%xxx%’,但是这样索引是有效的:select * from tbl1 where name like
‘xxx%’,所以谨慎的写你的SQL是很重要的。&&&&& 2. 关联查询和子查询&&&&& 数据库一个很重要的特点是关联查询,LEFT JOIN 和全关联,特别是多个表进行关联,因为每个关联表查询的时候,进行扫描的时候都是一个笛卡尔乘积的数量级,扫描数量很大,如果确实是需要进行关联操作,请给where或者on的条件进行索引。&&&&& 关联操作也是可能交给应用去操作的,看数据量的大小,如果数据量不是非常大,比如10万条以下,那么就可以交给程序去处理(提出笔误,特此修正),程序分别提取左右两个表的数据,然后进行循环的扫描处理,返回结果,这个过程同样非常耗费Web服务器的资源,那么就需要取决于你愿意把压力放在Web服务器上或者数据库服务器上了。&&&&& 子查询是在mysql5中支持的功能,比如:select * from tbl1 where id in(select id from tbl1),那样效率是非常非常低,要尽量避免使用子查询,要是我,绝对不用,呵呵。&&&&& 3. &一些耗费时间和资源的操作&&&&& SQL语句中一些浪费的操作,比如 DISTINCT、COUNT、GROUP BY、各种MySQL函数。这些操作都是比较耗资源的,我想应用最多的是count字句吧,如果使用count,尽量不要count(*),最好count一个字段,比如count(id),或者count(1),(据测
试效率其实是一样的),同样能够起到统计的作用。如果不是十分必要,尽量不要使用distinct操作,就是提取唯一值,你完全可以把这个操作交给脚本程
序去执行提取唯一值,减少MySQL的负担。group by
操作也是,确实需要分组的话,请谨慎的操作,如果是小批量的数据,可以考虑交给脚本程序去做。至于MySQL的函数,估计很多常用,比如有人喜欢把截取字符串也交给MySQL去操作,或者时间转换操作,使用比较多的函数像 SUBSTR(), CONCAT(), DATE_FORMAT(), TO_DAYS(), MAX(), MIN(), MD5() 等等,这些操作完全可以交给脚本程序去做,减轻MySQL的负担。&&&&& 4. 合理的建立索引&&&&& 索引的提升速度的一个非常重要的手段,索引在对一些经常进行select操作,并且值比较唯一的字段是相当有效的,比如主键的id字段,唯一的名字name字段等等。&&&&&
但是索引对于唯一值比较少的字段,比如性别gender字段,寥寥无几的类别字段等,意义不大,因为性别是50%的几率,索引几乎没有意义。对于
update/delete/insert非常频繁的表,建立索引要慎重考虑,因为这些频繁的操作同样对于索引的维护工作量也是很大的,最后反而得不偿
失,这个需要自己仔细考虑。索引同样不是越多越好,适当的索引会起到很关键的作用,不适当的索引,反而减低效率维护,增加维护索引的负担。&&&&& 5. 监控sql执行效率&&&&& 在select语句前面使用EXPLAIN字句能够查看当前这个select字句的执行情况,包括使用了什么操作、返回多少几率、对索引的使用情况如何等等,能够有效分析SQL语句的执行效率和合理程度。&&&&& 另外使用MySQL中本身的慢查询日志:slow-log,同样能够记录查询中花费时间比较多的SQL语句,好对相应的语句进行优化和改写。&&&&& 另外在MySQL终端下,使用show processlist命令能够有效的查看当前MySQL在进行的线程,包括线程的状态,是否锁表等等,可以实时的查看SQL执行情况,同时对一些锁表操作进行优化。&二、数据库服务器的架构和分布想法&&&&& 对于服务器的架构设计,这个其实是比较重要的,一个合理的设计,能够让应用更好的运行。当然,架构的设计,取决于你的应用和你硬件的实际情况。我就简单的说说几种不同的数据库架构设计方式,权当是一个个人的想法,希望能够有帮助。&&&&& 1. 单台服务器开多进程和端口&&&&& 单台MySQL服务器,如果使用长链接等等都无法解决负载太大,连接太多的问题,不凡考虑采用一台MySQL上使用多个端口开启多个MySQL守护进程的方法来缓解压力。当然,前提是你的应用必须支持多端口,并且你的cpu和内存足够运行多个守护进程。&&&&& 优点 是能够很好的缓解暂时服务器的压力,把不同的操作放在不同的端口,或者把不同的项目模块放在不同的端口去操作,良好的分担单个守护进程的压力。&&&&& 缺点 是数据可能会产生紊乱,同时可能会导致很多未知的莫名错误。呵呵&&&&& 2. 使用Master/Slave的服务器结构&&&&& Mysql本身具有同步功能,完全可以利用这个功能。构建 Master/Slave
的主从服务器结构,最少只需要两台MySQL服务器,我们可以把 Master 服务器用户更新操作,包括
update/delete/insert,把Slave服务器用于查询操作,包括 select 操作,然后两机进行同步。&&&&& 优点 是合理的把更新和查询的压力分担,并且能够避免锁表的问题。&&&&& 缺点 是更新部实时,如果网络繁忙,可能会存在延迟的问题,并且任何一台服务器down掉了都很麻烦。&&&&& 3. 使用分布式的散列存储&&&&& 这种结构适合大数据量,并且负载比较大,然后服务器比较充足的情况。分布式存储结构,简单的可以是
多台服务器,每台服务器功能是类似的,但是存储的数据不一样,比如做一个用户系统,那么把用户ID在1-10万以内的存储在A服务器,用户ID在
10-20万存储在B服务器,20-3-万存储在C服务器,以此类推。如果每个用户访问的服务器不足,可以构建组服务器,就是每组用户拥有多台服务器,比
如可以在某用户组建立两台MySQL服务器,一台Master,一台Slave,同样分离他们的更新和查询操作,或者可以设计成双向同步。同时,你的应用
程序必须支持跨数据库和跨服务器的操作能力。&&&&& 优点 是服务器的负载合理的被平摊,每台服务器都是负责一部分用户,如果一台服务器down掉了,不会影响其他用户ID的用户正常访问。同时添加节点比较容易,如果又增加了10万用户,那么又可以增加一个节点服务器,升级很方便。&&&&& 缺点 是任何一台数据库服务器down掉或者数据丢失,那么这部分服务器的用户将很郁闷,数据都没了,当然,这个需要良好的备份机制。&&&&& 另外,MySQL5.1已经http://jump.tngou.net?url=aHR0cDovL3d3dy5teXNxbC5vcmcvZG9jL3JlZm1hbi81LjEvemgvb3B0aW1pemF0aW9uLmh0bWw.org/doc/refman/5.1/zh/optimization.html">http://www.mysql.org/doc/refman/5.1/zh/optimization.html&&&&& 说明:以上纯属我个人的一些不成熟的观点和想法,同时部分想法是没有经过试验的,不能保证准确性,所以请读者自己试验考察,也希望这些想法能够有一些帮助。
这是数据库设计的优化方法。1、选取最适用的字段属性  MySQL可以很好的支持大数据量的存取,但是一般说来,数据库中
的表越小,在它上面执行的查询也就会越快。因此,在创建表的时候,为了获得更好的性能,我们可以将表中字段的宽度设得尽可能小。例如,在定义邮政编码这个
字段时,如果将其设置为CHAR(255),显然给数据库增加了不必要的空间,甚至使用VARCHAR这种类型也是多余的,因为CHAR(6)就可以很好
的完成任务了。同样的,如果可以的话,我们应该使用MEDIUMINT而不是BIGIN来定义整型字段。  另外一个提高效率的方法是在可能的情况下,应该尽量把字段设置为NOT NULL,这样在将来执行查询的时候,数据库不用去比较NULL值。  对于某些文本字段,例如“省份”或者“性别”,我们可以将它们定义为ENUM类型。因为在MySQL中,ENUM类型被当作数值型数据来处理,而数值型数据被处理起来的速度要比文本类型快得多。这样,我们又可以提高数据库的性能。2、使用连接(JOIN)来代替子查询(Sub-Queries) 
 MySQL从4.1开始支持SQL的子查询。这个技术可以使用SELECT语句来创建一个单列的查询结果,然后把这个结果作为过滤条件用在另一个查询
中。例如,我们要将客户基本信息表中没有任何订单的客户删除掉,就可以利用子查询先从销售信息表中将所有发出订单的客户ID取出来,然后将结果传递给主查
询,如下所示:DELETE FROM customerinfoWHERE CustomerID NOT in (SELECT CustomerID FROM salesinfo ) 
 使用子查询可以一次性的完成很多逻辑上需要多个步骤才能完成的SQL操作,同时也可以避免事务或者表锁死,并且写起来也很容易。但是,有些情况下,子查
询可以被更有效率的连接(JOIN).. 替代。例如,假设我们要将所有没有订单记录的用户取出来,可以用下面这个查询完成:SELECT * FROM customerinfoWHERE CustomerID NOT in (SELECT CustomerID FROM salesinfo )  如果使用连接(JOIN).. 来完成这个查询工作,速度将会快很多。尤其是当salesinfo表中对CustomerID建有索引的话,性能将会更好,查询如下:SELECT * FROM customerinfoLEFT JOIN salesinfoON customerinfo.CustomerID=salesinfo.CustomerIDWHERE salesinfo.CustomerID IS NULL  连接(JOIN).. 之所以更有效率一些,是因为 MySQL不需要在内存中创建临时表来完成这个逻辑上的需要两个步骤的查询工作。3、使用联合(UNION)来代替手动创建的临时表   MySQL 从 4.0 的版本开始支持 UNION 查询,它可以把需要使用临时表的两条或更多的 SELECT
查询合并的一个查询中。在客户端的查询会话结束的时候,临时表会被自动删除,从而保证数据库整齐、高效。使用 UNION
来创建查询的时候,我们只需要用 UNION作为关键字把多个 SELECT 语句连接起来就可以了,要注意的是所有 SELECT
语句中的字段数目要想同。下面的例子就演示了一个使用 UNION的查询。SELECT Name, Phone FROM clientUNIONSELECT Name, BirthDate FROM authorUNIONSELECT Name, Supplier FROM product4、事务 
 尽管我们可以使用子查询(Sub-Queries)、连接(JOIN)和联合(UNION)来创建各种各样的查询,但不是所有的数据库操作都可以只用一
条或少数几条SQL语句就可以完成的。更多的时候是需要用到一系列的语句来完成某种工作。但是在这种情况下,当这个语句块中的某一条语句运行出错的时候,
整个语句块的操作就会变得不确定起来。设想一下,要把某个数据同时插入两个相关联的表中,可能会出现这样的情况:第一个表中成功更新后,数据库突然出现意
外状况,造成第二个表中的操作没有完成,这样,就会造成数据的不完整,甚至会破坏数据库中的数据。要避免这种情况,就应该使用事务,它的作用是:要么语句
块中每条语句都操作成功,要么都失败。换句话说,就是可以保持数据库中数据的一致性和完整性。事物以BEGIN
关键字开始,COMMIT关键字结束。在这之间的一条SQL操作失败,那么,ROLLBACK命令就可以把数据库恢复到BEGIN开始之前的状态。BEGIN;INSERT INTO salesinfo SET CustomerID=14;UPDATE inventory SET Quantity=11WHERE item=’book’;COMMIT;  事务的另一个重要作用是当多个用户同时使用相同的数据源时,它可以利用锁定数据库的方法来为用户提供一种安全的访问方式,这样可以保证用户的操作不被其它的用户所干扰。5、锁定表 
 尽管事务是维护数据库完整性的一个非常好的方法,但却因为它的独占性,有时会影响数据库的性能,尤其是在很大的应用系统中。由于在事务执行的过程中,数
据库将会被锁定,因此其它的用户请求只能暂时等待直到该事务结束。如果一个数据库系统只有少数几个用户来使用,事务造成的影响不会成为一个太大的问题;但
假设有成千上万的用户同时访问一个数据库系统,例如访问一个电子商务网站,就会产生比较严重的响应延迟。  其实,有些情况下我们可以通过锁定表的方法来获得更好的性能。下面的例子就用锁定表的方法来完成前面一个例子中事务的功能。LOCK TABLE inventory WRITESELECT Quantity FROM inventoryWHEREItem=’book’;…UPDATE inventory SET Quantity=11WHEREItem=’book’;UNLOCK TABLES   这里,我们用一个 SELECT 语句取出初始数据,通过一些计算,用 UPDATE 语句将新值更新到表中。包含有 WRITE 关键字的
LOCK TABLE 语句可以保证在 UNLOCK TABLES 命令被执行之前,不会有其它的访问来对 inventory
进行插入、更新或者删除的操作。6、使用外键  锁定表的方法可以维护数据的完整
性,但是它却不能保证数据的关联性。这个时候我们就可以使用外键。例如,外键可以保证每一条销售记录都指向某一个存在的客户。在这里,外键可以把
customerinfo
表中的CustomerID映射到salesinfo表中CustomerID,任何一条没有合法CustomerID的记录都不会被更新或插入到
salesinfo中。CREATE TABLE customerinfo(CustomerID INT NOT NULL ,PRIMARY KEY ( CustomerID )) TYPE = INNODB;CREATE TABLE salesinfo(SalesID INT NOT NULL,CustomerID INT NOT NULL,PRIMARY KEY(CustomerID, SalesID),FOREIGN KEY (CustomerID) REFERENCES customerinfo(CustomerID) ON DELETECASCADE) TYPE = INNODB;   注意例子中的参数“ON DELETE CASCADE”。该参数保证当 customerinfo
表中的一条客户记录被删除的时候,salesinfo 表中所有与该客户相关的记录也会被自动删除。如果要在 MySQL
中使用外键,一定要记住在创建表的时候将表的类型定义为事务安全表 InnoDB类型。该类型不是 MySQL 表的默认类型。定义的方法是在
CREATE TABLE 语句中加上 TYPE=INNODB。如例中所示。7、使用索引   索引是提高数据库性能的常用方法,它可以令数据库服务器以比没有索引快得多的速度检索特定的行,尤其是在查询语句当中包含有MAX(),
MIN()和ORDERBY这些命令的时候,性能提高更为明显。那该对哪些字段建立索引呢?一般说来,索引应建立在那些将用于JOIN,
WHERE判断和ORDER
BY排序的字段上。尽量不要对数据库中某个含有大量重复的值的字段建立索引。对于一个ENUM类型的字段来说,出现大量重复值是很有可能的情况,例如
customerinfo中的“province”..
字段,在这样的字段上建立索引将不会有什么帮助;相反,还有可能降低数据库的性能。我们在创建表的时候可以同时创建合适的索引,也可以使用ALTER
TABLE或CREATE INDEX在以后创建索引。此外,MySQL从版本3.23.23开始支持全文索引和搜索。全文索引在MySQL
中是一个FULLTEXT类型索引,但仅能用于MyISAM
类型的表。对于一个大的数据库,将数据装载到一个没有FULLTEXT索引的表中,然后再使用ALTER TABLE或CREATE
INDEX创建索引,将是非常快的。但如果将数据装载到一个已经有FULLTEXT索引的表中,执行过程将会非常慢。8、优化的查询语句 
 绝大多数情况下,使用索引可以提高查询的速度,但如果SQL语句使用不恰当的话,索引将无法发挥它应有的作用。下面是应该注意的几个方面。首先,最好是
在相同类型的字段间进行比较的操作。在MySQL
3.23版之前,这甚至是一个必须的条件。例如不能将一个建有索引的INT字段和BIGINT字段进行比较;但是作为特殊的情况,在CHAR类型的字段和
VARCHAR类型字段的字段大小相同的时候,可以将它们进行比较。其次,在建有索引的字段上尽量不要使用函数进行操作。  例如,在一个DATE类型的字段上使用YEAE()函数时,将会使索引不能发挥应有的作用。所以,下面的两个查询虽然返回的结果一样,但后者要比前者快得多。SELECT * FROM order WHERE YEAR(OrderDate)<2001;SELECT * FROM order WHERE OrderDate<”″;  同样的情形也会发生在对数值型字段进行计算的时候:SELECT * FROM inventory WHERE Amount/7<24;SELECT * FROM inventory WHERE Amount<24*7;  上面的两个查询也是返回相同的结果,但后面的查询将比前面的一个快很多。第三,在搜索字符型字段时,我们有时会使用 LIKE 关键字和通配符,这种做法虽然简单,但却也是以牺牲系统性能为代价的。例如下面的查询将会比较表中的每一条记录。SELECT * FROM booksWHERE name like “MySQL%”  但是如果换用下面的查询,返回的结果一样,但速度就要快上很多:SELECT * FROM booksWHERE name>=”MySQL”and name<”MySQM”  最后,应该注意避免在查询中让MySQL进行自动类型转换,因为转换过程也会使索引变得不起作用。
1.索引作用在索引列上,除了上面提到的有序查找之外,数据库利用各种各样的快速定位技术,能够大大提高查询效率。特别是当数据量非常大,查询涉及多个表时,使用索引往往能使查询速度加快成千上万倍。例如,有3个未索引的表t1、t2、t3,分别只包含列c1、c2、c3,每个表分别含有1000行数据组成,指为1~1000的数值,查找对应值相等行的查询如下所示。&SELECT c1,c2,c3 FROM t1,t2,t3 WHERE c1=c2 AND c1=c3此查询结果应该为1000行,每行包含3个相等的值。在无索引的情况下处理此查询,必须寻找3个表所有的组合,以便得出与WHERE子句相配的那些行。而可能的组合数目为1000×1000×1000(十亿),显然查询将会非常慢。如果对每个表进行索引,就能极大地加速查询进程。利用索引的查询处理如下。(1)从表t1中选择第一行,查看此行所包含的数据。(2)使用表t2上的索引,直接定位t2中与t1的值匹配的行。类似,利用表t3上的索引,直接定位t3中与来自t1的值匹配的行。(3)扫描表t1的下一行并重复前面的过程,直到遍历t1中所有的行。在此情形下,仍然对表t1执行了一个完全扫描,但能够在表t2和t3上进行索引查找直接取出这些表中的行,比未用索引时要快一百万倍。利用索引,MySQL加速了WHERE子句满足条件行的搜索,而在多表连接查询时,在执行连接时加快了与其他表中的行匹配的速度。2.&&创建索引在执行CREATE TABLE语句时可以创建索引,也可以单独用CREATE INDEX或ALTER TABLE来为表增加索引。1.ALTER TABLEALTER TABLE用来创建普通索引、UNIQUE索引或PRIMARY KEY索引。&ALTER TABLE table_name ADD INDEX index_name (column_list)ALTER TABLE table_name ADD UNIQUE (column_list)ALTER TABLE table_name ADD PRIMARY KEY (column_list)&其中table_name是要增加索引的表名,column_list指出对哪些列进行索引,多列时各列之间用逗号分隔。索引名index_name可选,缺省时,MySQL将根据第一个索引列赋一个名称。另外,ALTER TABLE允许在单个语句中更改多个表,因此可以在同时创建多个索引。2.CREATE INDEXCREATE INDEX可对表增加普通索引或UNIQUE索引。&CREATE INDEX index_name ON table_name (column_list)CREATE UNIQUE INDEX index_name ON table_name (column_list)&table_name、index_name和column_list具有与ALTER TABLE语句中相同的含义,索引名不可选。另外,不能用CREATE INDEX语句创建PRIMARY KEY索引。3.索引类型在创建索引时,可以规定索引能否包含重复值。如果不包含,则索引应该创建为PRIMARY KEY或UNIQUE索引。对于单列惟一性索引,这保证单列不包含重复的值。对于多列惟一性索引,保证多个值的组合不重复。PRIMARY KEY索引和UNIQUE索引非常类似。事实上,PRIMARY KEY索引仅是一个具有名称PRIMARY的UNIQUE索引。这表示一个表只能包含一个PRIMARY KEY,因为一个表中不可能具有两个同名的索引。下面的SQL语句对students表在sid上添加PRIMARY KEY索引。&ALTER TABLE students ADD PRIMARY KEY (sid)&4.&&删除索引可利用ALTER TABLE或DROP INDEX语句来删除索引。类似于CREATE INDEX语句,DROP INDEX可以在ALTER TABLE内部作为一条语句处理,语法如下。&DROP INDEX index_name ON talbe_nameALTER TABLE table_name DROP INDEX index_nameALTER TABLE table_name DROP PRIMARY KEY&其中,前两条语句是等价的,删除掉table_name中的索引index_name。第3条语句只在删除PRIMARY KEY索引时使用,因为一个表只可能有一个PRIMARY KEY索引,因此不需要指定索引名。如果没有创建PRIMARY KEY索引,但表具有一个或多个UNIQUE索引,则MySQL将删除第一个UNIQUE索引。如果从表中删除了某列,则索引会受到影响。对于多列组合的索引,如果删除其中的某列,则该列也会从索引中删除。如果删除组成索引的所有列,则整个索引将被删除。&5.查看索引mysql& show&mysql& sh  · Table  表的名称。  · Non_unique  如果索引不能包括重复词,则为0。如果可以,则为1。  · Key_name  索引的名称。  · Seq_in_index  索引中的列序列号,从1开始。  · Column_name  列名称。  · Collation  列以什么方式存储在索引中。在MySQL中,有值‘A’(升序)或NULL(无分类)。  · Cardinality  索引中唯一值的数目的估计值。通过运行ANALYZE TABLE或myisamchk -a可以更新。基数根据被存储为整数的统计数据来计数,所以即使对于小型表,该值也没有必要是精确的。基数越大,当进行联合时,MySQL使用该索引的机会就越大。  · Sub_part  如果列只是被部分地编入索引,则为被编入索引的字符的数目。如果整列被编入索引,则为NULL。  · Packed  指示关键字如何被压缩。如果没有被压缩,则为NULL。  · Null  如果列含有NULL,则含有YES。如果没有,则该列含有NO。  · Index_type  用过的索引方法(BTREE, FULLTEXT, HASH, RTREE)。  · Comment6.什么情况下使用索引&&&&&& 表的主关键字自动建立唯一索引如zl_yhjbqk(用户基本情况)中的hbs_bh(户标识编号)表的字段唯一约束ORACLE利用索引来保证数据的完整性如lc_hj(流程环节)中的lc_bh+hj_sx(流程编号+环节顺序)直接条件查询的字段在SQL中用于条件约束的字段如zl_yhjbqk(用户基本情况)中的qc_bh(区册编号)select * from zl_yhjbqk where qc_bh=’7001’查询中与其它表关联的字段字段常常建立了外键关系如zl_ydcf(用电成份)中的jldb_bh(计量点表编号)select * from zl_ydcf a,zl_yhdb b where a.jldb_bh=b.jldb_bh and b.jldb_bh=’’查询中排序的字段排序的字段如果通过索引去访问那将大大提高排序速度select * from zl_yhjbqk order by qc_bh(建立qc_bh索引)select * from zl_yhjbqk where qc_bh=’7001’ order by cb_sx(建立qc_bh+cb_sx索引,注:只是一个索引,其中包括qc_bh和cb_sx字段)查询中统计或分组统计的字段select max(hbs_bh) from zl_yhjbqkselect qc_bh,count(*) from zl_yhjbqk group by qc_bh什么情况下应不建或少建索引表记录太少如果一个表只有5条记录,采用索引去访问记录的话,那首先需访问索引表,再通过索引表访问数据表,一般索引表与数据表不在同一个数据块,这种情况下ORACLE至少要往返读取数据块两次。而不用索引的情况下ORACLE会将所有的数据一次读出,处理速度显然会比用索引快。如表zl_sybm(使用部门)一般只有几条记录,除了主关键字外对任何一个字段建索引都不会产生性能优化,实际上如果对这个表进行了统计分析后ORACLE也不会用你建的索引,而是自动执行全表访问。如:select * from zl_sybm where sydw_bh=’5401’(对sydw_bh建立索引不会产生性能优化)经常插入、删除、修改的表对一些经常处理的业务表应在查询允许的情况下尽量减少索引,如zl_yhbm,gc_dfss,gc_dfys,gc_fpdy等业务表。数据重复且分布平均的表字段假如一个表有10万行记录,有一个字段A只有T和F两种值,且每个值的分布概率大约为50%,那么对这种表A字段建索引一般不会提高数据库的查询速度。经常和主字段一块查询但主字段索引值比较多的表字段如 gc_dfss(电费实收)表经常按收费序号、户标识编号、抄表日期、电费发生年月、操作 &标志来具体查询某一笔收款的情况,如果将所有的字段都建在一个索引里那将会增加数据的修改、插入、删除时间,从实际上分析一笔收款如果按收费序号索引就已 &经将记录减少到只有几条,如果再按后面的几个字段索引查询将对性能不产生太大的影响。对千万级MySQL数据库建立索引的事项及提高性能的手段一、注意事项:首先,应当考虑表空间和磁盘空间是否足够。我们知道索引也是一种数据,在建立索引的时候势必也会占用大量表空间。因此在对一大表建立索引的时候首先应当考虑的是空间容量问题。其次,在对建立索引的时候要对表进行加锁,因此应当注意操作在业务空闲的时候进行。二、性能调整方面:首当其冲的考虑因素便是磁盘I/O。物理上,应当尽量把索引与数据分散到不同的磁盘上(不考虑阵列的情况)。逻辑上,数据表空间与索引表空间分开。这是在建索引时应当遵守的基本准则。其次,我们知道,在建立索引的时候要对表进行全表的扫描工作,因此,应当考虑调大初始化参数db_file_multiblock_read_count的值。一般设置为32或更大。再次,建立索引除了要进行全表扫描外同时还要对数据进行大量的排序操作,因此,应当调整排序区的大小。&&&&9i之前,可以在session级别上加大sort_area_size的大小,比如设置为100m或者更大。&&&&9i以后,如果初始化参数workarea_size_policy的值为TRUE,则排序区从pga_aggregate_target里自动分配获得。最后,建立索引的时候,可以加上nologging选项。以减少在建立索引过程中产生的大量redo,从而提高执行的速度。MySql在建立索引优化时需要注意的问题设计好MySql的索引可以让你的数据库飞起来,大大的提高数据库效率。设计MySql索引的时候有一下几点注意:1,创建索引对于查询占主要的应用来说,索引显得尤为重要。很多时候性能问题很简单的就是因为我们忘了添加索引而造成的,或者说没有添加更为有效的索引导致。如果不加索引的话,那么查找任何哪怕只是一条特定的数据都会进行一次全表扫描,如果一张表的数据量很大而符合条件的结果又很少,那么不加索引会引起致命的性能下降。但是也不是什么情况都非得建索引不可,比如性别可能就只有两个值,建索引不仅没什么优势,还会影响到更新速度,这被称为过度索引。2,复合索引比如有一条语句是这样的:select * from users where area=’beijing’ and age=22;如果我们是在area和age上分别创建单个索引的话,由于mysql查询每次只能使用一个索引,所以虽然这样已经相对不做索引时全表扫描提高了很多效率,但是如果在area、age两列上创建复合索引的话将带来更高的效率。如果我们创建了(area, age,salary)的复合索引,那么其实相当于创建了(area,age,salary)、(area,age)、(area)三个索引,这被称为最佳左前缀特性。因此我们在创建复合索引时应该将最常用作限制条件的列放在最左边,依次递减。3,索引不会包含有NULL值的列只要列中包含有NULL值都将不会被包含在索引中,复合索引中只要有一列含有NULL值,那么这一列对于此复合索引就是无效的。所以我们在数据库设计时不要让字段的默认值为NULL。4,使用短索引对串列进行索引,如果可能应该指定一个前缀长度。例如,如果有一个CHAR(255)的 列,如果在前10 个或20 个字符内,多数值是惟一的,那么就不要对整个列进行索引。短索引不仅可以提高查询速度而且可以节省磁盘空间和I/O操作。5,排序的索引问题mysql查询只使用一个索引,因此如果where子句中已经使用了索引的话,那么order by中的列是不会使用索引的。因此数据库默认排序可以符合要求的情况下不要使用排序操作;尽量不要包含多个列的排序,如果需要最好给这些列创建复合索引。6,like语句操作一般情况下不鼓励使用like操作,如果非使用不可,如何使用也是一个问题。like “%aaa%” 不会使用索引而like “aaa%”可以使用索引。7,不要在列上进行运算select * from users whereYEAR(adddate)8,不使用NOT IN和操作NOT IN和操作都不会使用索引将进行全表扫描。NOT IN可以NOT EXISTS代替,id3则可使用id&3 or id
多数MySQL规范在网上也都能找得到相关的分享,在这里要分享的是老叶个人认为比较重要的,或者容易被忽视的,以及容易被混淆的一些地方。& &1、默认使用InnoDB引擎& &【老叶观点】已多次呼吁过了,InnoDB适用于几乎99%的MySQL应用场景,而且在MySQL 5.7的系统表都改成InnoDB了,还有什么理由再死守MyISAM呢。& &此外,频繁读写的InnoDB表,一定要使用具有自增/顺序特征的整型作为显式主键。& &【参考】:。& &2、字符集选择utf-8& &【老叶观点】若为了节省磁盘空间,则建议选择latin1。建议选择utf-8通常是为了所谓的“通用性”,但事实上用户提交的utf-8数据也一样可以以latin1字符集存储。& &用latin1存储utf-8数据可能遇到的麻烦是,如果有基于中文的检索时,可能无法100%准确(老叶亲自简单测试常规的中文完检索全不是问题,也就是一般的中文对比是没问题的)。& &用latin1字符集存储utf-8数据的做法是:在web端(用户端)的字符集是utf-8,后端程序也采用utf-8来处理,但
character_set_client、character_set_connection、character_set_results、
character_set_database、character_set_server 这几个都是
latin1,且数据表、字段的字符集也是latin1。或者说数据表采用latin1,每次连接后执行 SET NAMES LATIN1 即可。& &【参考】:。& &3、InnoDB表行记录物理长度不超过8KB& &【老叶观点】InnoDB的data page默认是16KB,基于B+Tree的特点,一个data
page中需要至少存储2条记录。因此,当实际存储长度超过8KB(尤其是TEXT/BLOB列)的大列(large
column)时会引起“page-overflow存储”,类似ORACLE中的“行迁移”。& &因此,如果必须使用大列(尤其是TEXT/BLOB类型)且读写频繁的话,则最好把这些列拆分到子表中,不要和主表放在一起存储。如果不太频繁,可以考虑继续保留在主表中。& &当然了,如果将 innodb_page_size 选项修改成 8KB,那么行记录物理长度建议不超过http://jump.tngou.net?url=aHR0cDovL2lteXNxbC5jb20vMjAxNC8wOS8yOC9teXNxbC1vcHRpbWl6YXRpb24tY2FzZS1ibG9iLXN0b3JlZC1pbi1pbm5vZGItb3B0aW1pemF0aW9uLnNodG1simization-case-blob-stored-in-innodb-optimization.shtml" target="_blank">[MySQL优化案例]系列 — 优化InnoDB表BLOB列的存储效率。& &4、是否使用分区表& &【老叶观点】在一些使用分区表后明显可以提升性能或者运维便利性的场景下,还是建议使用分区表。& &比如老叶就在zabbix的数据库采用TokuDB引擎的前提下,又根据时间维度使用了分区表。这样的好处是保证zabbix日常应用不受到影响前提下,方便管理员例行删除过去http://jump.tngou.net?url=aHR0cDovL2lteXNxbC5jb20vMjAxNC8wNi8yNC9taWdyYXRlLXphYmJpeC1kYi10by10b2t1ZGIuc2h0bWwstrong>参考】:。& &5、是否使用存储过程、触发器& &【老叶观点】在一些合适的场景下,用存储过程、触发器也完全没问题。& &我们以前就是利用存储完成游戏业务逻辑处理,性能上不是问题,而且一旦需求有变更,只需修改存储过程,变更代价很低。我们还利用触发器维护一个频繁更新的表,对这个表的所有变更都将部分字段同步更新到另一个表中(类似物化视图的变相实现),也不存在性能问题。& &不要把MySQL的存储过程和触发器视为洪水猛兽,用好的话,没有问题的,真遇到问题了再优化也不迟。另外,MySQL因为没有物化视图,因此视图能不用就尽量少用吧。& &6、选择合适的类型& &【老叶观点】除了常见的建议外,还有其他几个要点:& &6.1、用INT UNSIGNED存储IPV4地址,用INET_ATON()、INET_NTOA()进行转换,基本上没必要使用CHAR(15)来存储。& &6.2、枚举类型可以使用ENUM,ENUM的内部存储机制是采用TINYINT或SMALLINT(并非CHAR/VARCHAR),性能一点都不差,记住千万别用CHAR/VARCHAR 来存储枚举数据。&
&6.3、还个早前一直在传播的“常识性误导”,建议用TIMESTAMP取代DATETIME。其实从5.6开始,建议优先选择DATETIME存储日
期时间,因为它的可用范围比TIMESTAMP更大,物理存储上仅比TIMESTAMP多1个字节,整体性能上的损失并不大。& &6.4、所有字段定义中,默认都加上NOT
NULL约束,除非必须为NULL(但我也想不出来什么场景下必须要在数据库中存储NULL值,可以用0来表示)。在对该字段进行COUNT()统计时,
统计结果更准确(值为NULL的不会被COUNT统计进去),或者执行 WHERE column IS NULL 检索时,也可以快速返回结果。& &6.5、尽可能不要直接 SELECT * 读取全部字段,尤其是表中存在 TEXT/BLOB
大列的时候。可能本来不需要读取这些列,但因为偷懒写成 SELECT * 导致内存buffer
pool被这些“垃圾”数据把真正需要缓冲起来的数据给洗出去了。& &8、关于索引& &【老叶观点】除了常见的建议外,还有几个要点:& &8.1、超过20个长度的字符串列,最好创建前缀索引而非整列索引(例如:ALTER TABLE t1 ADD
INDEX(user(20))),可以有效提高索引利用率,不过它的缺点是对这个列排序时用不到前缀索引。前缀索引的长度可以基于对该字段的统计得出,
一般略大于平均长度一点就可以了。& &8.2、定期用 pt-duplicate-key-checker 工具检查并删除重复的索引。比如 index idx1(a, b) 索引已经涵盖了 index idx2(a),就可以删除 idx2 索引了。& &8.3、有多字段联合索引时,WHERE中过滤条件的字段顺序无需和索引一致,但如果有排序、分组则就必须一致了。& &比如有联合索引 idx1(a, b, c),那么下面的SQL都可以完整用到索引:SELECT&...&WHERE&b&=&?&AND&c&=&?&AND&a&=&?;&&--注意到,WHERE中字段顺序并没有和索引字段顺序一致
SELECT&...&WHERE&b&=&?&AND&a&=&?&AND&c&=&?;
SELECT&...&WHERE&a&=&?&AND&b&IN&(?,&?)&AND&c&=&?;
SELECT&...&WHERE&a&=&?&AND&b&=&?&ORDER&BY&c;
SELECT&...&WHERE&a&=&?&AND&b&IN&(?,&?)&ORDER&BY&c;
SELECT&...&WHERE&a&=&?&ORDER&BY&b,&c;
SELECT&...&ORDER&BY&a,&b,&c;&&--&可利用联合索引完成排序& &而下面几个SQL则只能用到部分索引:SELECT&...&WHERE&b&=&?&AND&a&=&?;&&&--&只能用到&(a,&b)&部分
SELECT&...&WHERE&a&IN&(?,&?)&AND&b&=&?;&&&--&只能用到&(a,&b)&部分
SELECT&...&WHERE&a&=&?&AND&c&=&?;&&&--&只能用到&(a)&部分
SELECT&...&WHERE&a&=&?&AND&b&IN&(?,&?);&&&&--&只能用到&(a,&b)&部分
SELECT&...&WHERE&(a&BETWEEN&?&AND&?)&AND&b&=&?;&&&--&只能用到&(a)&部分,注意BETWEEN和IN的区别
SELECT&...&WHERE&a&=&?&AND&(b&BETWEEN&?&AND&?)&AND&c&=&?;&&&&--&只能用到&(a,&b)&部分& &下面的几个SQL完全用不到该索引:SELECT&...&WHERE&b&=&?;
SELECT&...&WHERE&b&=&?&AND&c&=&?;
SELECT&...&WHERE&b&=&?&AND&c&=&?;
SELECT&...&ORDER&BY&b;
SELECT&...&ORDER&BY&b,&a;& &从上面的几个例子就能看的出来,以http://jump.tngou.net?url=aHR0cDovL2Rldi5teXNxbC5jb20vZG9jL3JlZm1hbi81LjYvZW4vc3dpdGNoYWJsZS1vcHRpbWl6YXRpb25zLmh0bWwp>& &此外,有些时候查询优化器指定的索引或执行计划可能并不是最优的,可以手工指定最优索引,或者修改session级的
选项,关闭某些导致效果反而更差的特性(比如index merge通常是好事,但也遇到过用上index merge后反而更差的,这时候要么强制指定其中一个索引,要么可以临时关闭 index merge 特性)。& &9、其他& &9.1、哪怕是基于索引的条件过滤,如果优化器意识到总共需要扫描的数据量超过30%时(ORACLE里貌似是20%,MySQL目前是30%,没准以后会调整),就会直接改变执行计划为全表扫描,不再使用索引。& &9.2、多表JOIN时,要把过滤性最大(不一定是数据量最小http://jump.tngou.net?url=aHR0cHM6Ly93d3cucGVyY29uYS5jb20vZG9jL3BlcmNvbmEtdG9vbGtpdC8yLjIvcHQtcXVlcnktZGlnZXN0Lmh0bWw的索引完成排序。&http://jump.tngou.net?url=aHR0cHM6Ly9naXRodWIuY29tL2JveC9BbmVtb21ldGVy此如果看到执行计划中有 Using filesort,优先创建排序索引吧。& &9.4、利用
定期分析slow query log,并结合
构建slow query log分析及优化系统。
1、UNION查询;
2、用到TEMPTABLE算法或者是UNION查询中的视图;
3、ORDER&BY和GROUP&BY的子句不一样时;
4、表连接中,ORDER&BY的列不是驱动表中的;
5、DISTINCT查询并且加上ORDER&BY时;
6、SQL中用到SQL_SMALL_RESULT选项时;
7、FROM中的子查询;
8、子查询或者semi-join时创建的表;& &EXPLAIN 查看执行计划结果的 Extra 列中,如果包含
就表示会用到临时表。& &当然了,如果临时表中需要存储的数据量超过了上限(
中取其大者),这时候就需要生成基于磁盘的临时表了。& &在以下几种情况下,会创建磁盘临时表:1、数据表中包含BLOB/TEXT列;
2、在&GROUP&BY&或者&DSTINCT&的列中有超过&512字符&的字符类型列(或者超过&512字节的&二进制类型列,在5.6.15之前只管是否超过512字节);
3、在SELECT、UNION、UNION&ALL查询中,存在最大长度超过512的列(对于字符串类型是512个字符,对于二进制类型则是512字节);
4、执行SHOW&COLUMNS/FIELDS、DESCRhttp://jump.tngou.net?url=aHR0cHM6Ly9kZXYubXlzcWwuY29tL2RvYy9yZWZtYW4vNS43L2VuL3NlcnZlci1zeXN0ZW0tdmFyaWFibGVzLmh0bWwjc3lzdmFyX2ludGVybmFsX3RtcF9kaXNrX3N0b3JhZ2VfZW5naW5l="/doc/refman/5.7/en/server-system-variables.html#sysvar_internal_tmp_diskhttp://jump.tngou.net?url=aHR0cHM6Ly9kZXYubXlzcWwuY29tL2RvYy9yZWZtYW4vNS42L2VuL3NlcnZlci1zeXN0ZW0tdmFyaWFibGVzLmh0bWwjc3lzdmFyX2RlZmF1bHRfdG1wX3N0b3JhZ2VfZW5naW5l在这以前,只能使用 MyISAM。而在5.6.3以后新增的系统选项
是控制 CREATE TEMPORARY TABLE 创建的临时表的引擎类型,在以前默认是MEMORY,不要把这二者混淆了。& &见下例:mysql&&set&default_tmp_storage_engine&=&&InnoDB&;
-rw-rw----&&&1&mysql&mysql&&8558&Jul&&7&15:22&#sql4b0e_10_0.frm&--&InnoDB引擎的临时表
-rw-rw----&&&1&mysql&mysql&98304&Jul&&7&15:22&#sql4b0e_10_0.ibd
-rw-rw----&&&1&mysql&mysql&&8558&Jul&&7&15:25&#sql4b0e_10_2.frm
mysql&&set&default_tmp_storage_engine&=&&MyISAM&;
-rw-rw----&&&1&mysql&mysql&&&&&0&Jul&&7&15:25&#sql4b0e_10_2.MYD&--&MyISAM引擎的临时表
-rw-rw----&&&1&mysql&mysql&&1024&Jul&&7&15:25&#sql4b0e_10_2.MYI
mysql&&set&default_tmp_storage_engine&=&&MEMORY&;
-rw-rw----&&&1&mysql&mysql&&8558&Jul&&7&15:26&#sql4b0e_10_3.frm&--&MEMORY引擎的临时表
Mysql安装简单,速度较快,功能丰富。另外它还是开源运动的标杆,它的伟大成就向我们展示了一个成功的公司是可以建立在开源代码之上的。然而用过mysql的人都曾对着显示器挥舞过拳头。但你不可能发明一种每秒能保存成千上万行互联网数据,并且一点错误都没有的技术吧。&& & & & && & & & &
了在这个夏天躁起来,我们列举了8个抱怨开源关系型数据库的理由。下面列举的理由中不仅限于
MySQL,有一些是针对关系型数据库的。如果我们没有理清楚关系型数据库和
MySQL,我们将会永远陷入90年代的思想上。我们需要推倒然后重建这些。或者我们转向使用一个最近流行的,存在时间没有长到可以列出一堆像下面一样的
理由的数据库。&& & & & && & & & &
根深蒂固的bugs 任何大的软件包都有 bug。但稍微深入了解一下,就会发现和 Mysql 相关的 bugs 自成体系。突然你就需要留心,因为 NULL 并不是以同样的方式出现,外键约束也没有像你想像的那样执行,连主键自动增长也会出错。小问题大量存在,而且并不总是可以修复,这就是为什么一些人保持一个列表。还好 MySQL 维护着一个非常好的 bug 报告系统,让我们可以知道我些我们无法想像的事情,知道其他人也在经受同样的磨难。& & & && & & & &
关系表的不灵活性关系表具有条理性,条理性是好的——但是,它使得程序员不得不编造或硬塞一些数据到已经定义好模式的列中。NoSQL开始越来越受到欢迎的原因之
一,就是它为程序员提供了足够的灵活性,来加速数据库的使用。如果一个街道地址需要增加一行,那么,你可以将它很容易地插入到一个NoSQL文档中。如果
你想添加一个完整的新的数据块,无论它包含什么内容,文档模型也可以原封不动地接受你的数据,而不必改为它要求的数据格式。& & & &
试想一下,你用整数格式建立了一个全部是邮编的表格。这个表是十分高效的,它执行的规则也很好。突然一次,有人上传了一个使用了连字符的九位数邮编。或者还有可能,你得到了一位来自加拿大客户的信件,上面写有邮政编码。这时,一切都乱了。老板要求网站要在几小时内恢复正常工作。然而,现在已经没有时间来重建数据库。程序员可以做什么?也许,可以使用黑客手段把加拿
大邮政编码由base64的数字格式改为base
10格式?或者设置一个使用转义编码的辅助表格,用来说明真正的邮政编码或者其他?谁知道呢?到处都有黑客,他们都是危险的。但你没有时间来搞定它。MySQL的关联规则让每个人都诚实和谨慎,但它能强制我们避开易受攻击和欺骗的麻烦。& & & && & & & &
JOIN联合查询曾几何时,将数据分表保存是计算机科学史上的伟大创新。分开后的表不仅结构简单,也简化了使用。但它却需要使用join语句进行查询。sql通过一系列join构建的复杂查询将开发者推入了困惑与绝望的深渊。而且存储引擎也需要以最优的方式来高效地解析join语句。开发者需要绞尽脑汁编写查询语句,然后数据库对其进行解析。&& & & & && & & & &
这就是很多注重运行速度的开发者放弃数据分表转而使用不规范数据表的原因。不区分数据实体,将所有数据保存到一个大表中——以避免复杂的查询。这样确实很快,并且服务器也不会耗尽内存。磁盘空间现在很廉价。8TB的磁盘已经在售,更大的也要上市了。我们不再需要为使用join而绞尽脑汁了。& & & && & & & &
分支的混乱是的,一个可靠的、得到良好支持的MySQL分支,可以带来竞争和选择,但是它也引起困惑和混乱。更糟糕的是,一个称为MariaDB的MySQL分支,
Widenius维护着。他同样也在参与编写MySQL。那么,MariaDB是真正独立的值得我们拥护的吗?或者它是MySQL?我们是否应该坚持使用
由创建原始MySQL数据库的组织运营的核心代码?或者我们应该加入那些被认为更聪明的,往往很酷的背叛者?还有,我们应当如何获得关于兼容性的信息?一方面,我们被确信MariaDB和MySQL十分地相似。另一方面,我们要相信有差异——不然为什么大家都在争论它?也许它们在性能和我们查询的范围内,在两个阵营中工作方式相同?但也许他们不同-或者将来会不同。&& & & & && & & & &
存储引擎混乱MySQL不是事实上的同一的数据库;它由几个数据库组成,它们的大多数细节都被统一的表面所掩盖。在开始的时候,有一个MyISAM引擎,它很快但是在前后一致上不能做到完备。有时候你需要速度并且可以接受不一致的结果时是很好的。当人们需要更多时,具备完整事务支持的InnoDB出现了。但这还不够。现在,它可能有20种存储引擎的选择——这足以使一个数据库管理员疯狂。当
然,有些时候在不同的存储引擎之间切换而不必重写你的SQL是很好的,但是切换后总会带来混乱。这个表格我选择的引擎是 MyISAM 还是
innoDB 呢?或者,我决定输出的数据是CSV格式的吗?&& & & && & & & &
盈利的动机虽然 MySQL
是一款成功的开源产品,但它仍然是一门生意,里面满是靠它获得薪水的专业开发者。当大多数用户在持续地享受开源许可证带来的最佳体验时,毫无疑问这家公司
还在为赚取足够的钱来维持运营而努力。这导致自由代码在“社区版”和出售给企业的完整产品之间产生了奇怪的分岐。你应该付钱吗?你在这里挣到了多少钱?在社区版之上开展经营行为是否公平?企业版中额外的功能,是否只是一个噱头来引诱我们不断付费呢?这至少说明一点,它是另一组需要回答的问题。选用哪个版本?遵照哪种许可证?选用它的哪个功能集?& & & & && & & & &
原生 JSON 支持的缺乏看 MySQL 的年龄最好的办法是安装它,然后你会意识到需要添加更多的驱动程序使它可用。MySQL 通常在 3306
端口上通信,它一般输出的是它自己难以理解的格式化数据。如果你想让你的代码和它通信,你必须添加另一层的代码,将 MySQL
的语言转换成有用的东西。这些层的代码,以库的形式分发,经常需要人们购买一个商业的许可证。现代数据存储层通常直接以 JSON 通信。虽然 MySQL 和 MariaDB 现在有能力解析 SQL 中的 JSON 部分,但这还远远不够好,原生的 JSON 接口已经在 CouchDB,MongoDB,或任何最新的工具中广泛使用。& & & & && & & & &
封闭源和专有模块的兴起我说过 MySQL
是开源的吗?它是,但除了一些在”开源核心“周边开发的一些较新的、非开源的代码、专有模块。程序员需要吃饭,Oracle需要拿它的辛苦成果来换钱,这
是商业的现实之一。它不像那些医院,使用 MySQL 可以免费医疗护理。它不象那些农民,使用 MySQL 可以赠送食物。要求 MySQL
始终坚持在一个很高的标准是有点不公平的,因为开源的成功可能是一个圈套。这是因为它开始可以免费,但并不意味着它可以始终如此。如果企业需要许多新的功
能,他们将不得不用这种或那种方式付费。有时向 Oracle 付费,比自己来编写代码要便宜得多。有时商业的、不开源的代码是有意义的。事实不言而喻。
相同点:&&&&& truncate 和不带 where 子句的 delete,以及 drop 都会删除表内的数据&&&&& 不同点:&&&&& 1. truncate 和 delete 只删除数据不删除表的结构(定义)&&&&&&&&&&& drop 语句将删除表的结构被依赖的约束(constrain)、触发器(trigger)、索引(index);依赖于该表的存储过程/函数将保留,但是变为 invalid 状态。&&&&& 2. delete 语句是数据库操作语言(dml),这个操作会放到 rollback segement 中,事务提交之后才生效;如果有相应的 trigger,执行的时候将被触发。&&&&&&&& truncate、drop 是数据库定义语言(ddl),操作立即生效,原数据不放到 rollback segment 中,不能回滚,操作不触发 trigger。&&&&& 3.delete 语句不影响表所占用的 extent,高水线(high watermark)保持原位置不动&&&&&&&&&显然drop 语句将表所占用的空间全部释放。&&&&&&&& truncate 语句缺省情况下见空间释放到 minextents个 extent,除非使用truncate 会将高水线复位(回到最开始)。&&&&& 4.速度,一般来说: drop& truncate & delete&&&&& 5.安全性:小心使用 drop 和 truncate,尤其没有备份的时候.否则哭都来不及&&&&&&& 使用上,想删除部分数据行用 delete,注意带上where子句. 回滚段要足够大.&&&&&&& 想删除表,当然用 drop& &&&&& 想保留表而将所有数据删除,如果和事务无关,用truncate即可。如果和事务有关,或者想触发trigger,还是用delete。&&&&&&& 如果是整理表内部的碎片,可以用truncate跟上reuse stroage,再重新导入/插入数据。
&& 碰到过好几次这样的题目,可每次都不能答的完全正确,现在大概列出如下:(望各位补充)&&&&& 1.数据库的设计&&&&&&&&&&& 尽量把数据库设计的更小的占磁盘空间。&& &&&1).尽可能使用更小的整数类型。(mediumint就比int更合适)。&&&&&&2).尽可能的定义字段为not null,除非这个字段需要null。&&&&& 3).如果没有用到变长字段的话比如varchar,那就采用固定大小的纪录格式比如char。&&&&& 4).表的主索引应该尽可能的短,这样的话每条纪录都有名字标志且更高效。&&&&& 5).只创建确实需要的索引。索引有利于检索记录,但是不利于快速保存记录。如果总是要在表的组合字段上做搜索,那么就在这些字段上创建索引。索引的第一部分必须是最常使用的字段。如果总是需要用到很多字段,首先就应该多复制这些字段,使索引更好的压缩。&&&&& 6).所有数据都得在保存到数据库前进行处理。&&&&& 7).所有字段都得有默认值。&&&&& 8).在某些情况下,把一个频繁扫描的表分成两个速度会快好多。在对动态格式表扫描以取得相关记录时,它可能使用更小的静态格式表的情况下更是如此。&&&&& 2.系统的用途&&&&& 1).尽量使用长连接。&&&&& 2).explain 复杂的SQL语句。&&&&& 3).如果两个关联表要做比较话,做比较的字段必须类型和长度都一致。&&&&& 4).LIMIT语句尽量要跟 order by 或者 distinct。这样可以避免做一次full table scan。&&&&& 5).如果想要清空表的所有纪录,建议用 truncate table tablename 而不是 delete from tablename。&&&&& 6).能使用 STORE PROCEDURE 或者 USER FUNCTION的时候。&&&&& 7).在一条insert语句中采用多重纪录插入格式,而且使用 load data infile 来导入大量数据,这比单纯的indert快好多。&&&&& 8).经常 OPTIMIZE TABLE 来整理碎片。&&&&& 9).还有就是 date 类型的数据如果频繁要做比较的话尽量保存在 unsigned int 类型比较快。&&&&& 3.系统的瓶颈&&&&& 1).磁盘搜索&&&&&&&&&&& 并行搜索,把数据分开存放到多个磁盘中,这样能加快搜索时间.&&&&& 2).磁盘读写(IO)&&&&&&&&&&& 可以从多个媒介中并行的读取数据。&&&&& 3).CPU周期&&&&&&&&&&& 数据存放在主内存中,这样就得增加CPU的个数来处理这些数据。&&&&&&4).内存带宽&&&&&&&&&&& 当CPU要将更多的数据存放到CPU的缓存中来的话,内存的带宽就成了瓶颈.
& 最近由于需要大概研究了一下MYSQL的随机抽取实现方法。举个例子,要从tablename表中随机提取一条记录,大家一般的写法就是:SELECT * FROM tablename ORDER BY RAND() LIMIT 1。&&&&& 但是,后来我查了一下MYSQL的官方手册,里面针对RAND()的提示大概意思就是,在ORDER
BY从句里面不能使用RAND()函数,因为这样会导致数据列被多次扫描。但是在MYSQL 3.23版本中,仍然可以通过ORDER BY
RAND()来实现随机。&&&&& 但是真正测试一下才发现这样效率非常低。一个15万余条的库,查询5条数据,居然要8秒以上。查看官方手册,也说rand()放在ORDER BY 子句中会被执行多次,自然效率及很低。You cannot use a column with RAND() values in an ORDER BY clause, because ORDER BY would evaluate the column multiple times.&&&&& 搜索Google,网上基本上都是查询max(id) * rand()来随机获取数据。SELECT *FROM `table` AS t1 JOIN (SELECT ROUND(RAND() * (SELECT MAX(id) FROM `table`)) AS id) AS t2WHERE t1.id &= t2.idORDER BY t1.id ASC LIMIT 5;&&&&& 但是这样会产生连续的5条记录。解决办法只能是每次查询一条,查询5次。即便如此也值得,因为15万条的表,查询只需要0.01秒不到。&&&&& 下面的语句采用的是JOIN,mysql的上有人使用SELECT *FROM `table`WHERE id &= (SELECT FLOOR( MAX(id) * RAND()) FROM `table` )ORDER BY id LIMIT 1;&&&&& 我测试了一下,需要0.5秒,速度也不错,但是跟上面的语句还是有很大差距。总觉有什么地方不正常。&&&&& 于是我把语句改写了一下。SELECT * FROM `table`WHERE id &= (SELECT floor(RAND() * (SELECT MAX(id) FROM `table`)))&ORDER BY id LIMIT 1;&&&&& 这下,效率又提高了,查询时间只有0.01秒&&&&& 最后,再把语句完善一下,加上MIN(id)的判断。我在最开始测试的时候,就是因为没有加上MIN(id)的判断,结果有一半的时间总是查询到表中的前面几行。&&&&& 完整查询语句是:SELECT * FROM `table`WHERE id &= (SELECT floor( RAND() * ((SELECT MAX(id) FROM
`table`)-(SELECT MIN(id) FROM `table`)) + (SELECT MIN(id) FROM
`table`)))&ORDER BY id LIMIT 1;SELECT *FROM `table` AS t1 JOIN (SELECT ROUND(RAND() * ((SELECT MAX(id) FROM
`table`)-(SELECT MIN(id) FROM `table`))+(SELECT MIN(id) FROM `table`))
AS id) AS t2WHERE t1.id &= t2.idORDER BY t1.id LIMIT 1;&&&&& 最后在php中对这两个语句进行分别查询10次,&&&&&&&&&&& 前者花费时间 0.147433 秒&&&&&&&&&&& 后者花费时间 0.015130 秒&&&&& 看来采用JOIN的语法比直接在WHERE中使用函数效率还要高很多。

我要回帖

更多关于 mysql数据库语句 的文章

 

随机推荐