zoukankan      html  css  js  c++  java
  • Database | SQL

    Basic of MySQL

    创建数据库:

    1 mysql> create database xxj;
    2 Query OK, 1 row affected (0.00 sec)

    列举数据库:

    1 mysql> show databases;
    2 +--------------------+
    3 | Database           |
    4 +--------------------+
    5 | information_schema |
    6 | mysql              |
    7 | xxj                |
    8 +--------------------+

    进入某个数据库:

    1 mysql> use xxj;
    2 Database changed

    创建表:

    1 mysql> create table test(id int primary key auto_increment, name varchar(20) not null, pwd varchar(20) default '123');
    2 Query OK, 0 rows affected (0.01 sec)

    设置了主键,默认值,not null;

    删除表:

    mysql> drop table test;
    Query OK, 0 rows affected (0.00 sec)

    查看表:

    1 mysql> desc test;
    2 +-------+-------------+------+-----+---------+----------------+
    3 | Field | Type        | Null | Key | Default | Extra          |
    4 +-------+-------------+------+-----+---------+----------------+
    5 | id    | int(11)     | NO   | PRI | NULL    | auto_increment |
    6 | name  | varchar(20) | NO   |     | NULL    |                |
    7 | pwd   | varchar(20) | YES  |     | 123     |                |
    8 +-------+-------------+------+-----+---------+----------------+
    9 3 rows in set (0.01 sec)

    改变表:

    1 mysql> alter table test add column addr text;
    2 Query OK, 0 rows affected (0.34 sec)
    3 Records: 0  Duplicates: 0  Warnings: 0
    1 mysql> alter table test drop column addr;
    2 Query OK, 0 rows affected (0.01 sec)
    3 Records: 0  Duplicates: 0  Warnings: 0

    删除主键:

    mysql> alter table test drop primary key;
    Query OK, 0 rows affected (0.01 sec)
    Records: 0  Duplicates: 0  Warnings: 0

    添加主键:

    1 mysql> alter table test add primary key(id);
    2 Query OK, 0 rows affected (0.01 sec)
    3 Records: 0  Duplicates: 0  Warnings: 0

    插入记录:

    1 mysql> insert into test(name, pwd) values("xxj", "1323");
    2 Query OK, 1 row affected, 1 warning (0.00 sec)

    更新:

     1 mysql> update test set pwd ='2222' where id = 1;
     2 Query OK, 1 row affected (0.03 sec)
     3 Rows matched: 1  Changed: 1  Warnings: 0
     4 
     5 mysql> select * from test;
     6 +----+------+------+
     7 | id | name | pwd  |
     8 +----+------+------+
     9 |  1 | xxj  | 2222 |
    10 +----+------+------+
    11 1 row in set (0.00 sec)

    清空表:

    1 mysql> delete from test;
    2 Query OK, 2 rows affected (0.00 sec)
    3 
    4 mysql> select * from test;
    5 Empty set (0.00 sec)

    删除记录:

    1 mysql> delete from test where id = 4;
    2 Query OK, 1 row affected (0.00 sec)

    查询:

     1 mysql> select * from test where name like 'xxj%';
     2 +----+------+------+
     3 | id | name | pwd  |
     4 +----+------+------+
     5 |  7 | xxj  | 123  |
     6 |  6 | xxj3 | 123  |
     7 |  8 | xxj2 | 123  |
     8 +----+------+------+
     9 3 rows in set (0.00 sec)
    10 
    11 mysql> select * from test where name like '%xxj%';
    12 +----+-------+------+
    13 | id | name  | pwd  |
    14 +----+-------+------+
    15 |  7 | xxj   | 123  |
    16 |  6 | xxj3  | 123  |
    17 |  8 | xxj2  | 123  |
    18 | 11 | xxxj2 | 123  |
    19 +----+-------+------+
    20 4 rows in set (0.00 sec)

    group/having:

     1 mysql> select count(*) as c from xxb group by age having c > 0;
     2 +---+
     3 | c |
     4 +---+
     5 | 2 |
     6 | 1 |
     7 | 1 |
     8 | 1 |
     9 +---+
    10 4 rows in set (0.00 sec)

     还有distinct去重,order by 排序等。

    高级一点

    join

     1 mysql> create table xxa(id int primary key auto_increment, name varchar(20));
     2 Query OK, 0 rows affected (0.01 sec)
     3 
     4 mysql> create table xxb(id int primary key auto_increment, age int);
     5 Query OK, 0 rows affected (0.00 sec)
     6 
     7 mysql> show tables;
     8 +---------------+
     9 | Tables_in_xxj |
    10 +---------------+
    11 | test          |
    12 | xxa           |
    13 | xxb           |
    14 +---------------+
    15 3 rows in set (0.00 sec)
    16 
    17 mysql> insert into xxa(name) values('xxj'), ('xxa'), ('xxb'), ('xxc');
    18 Query OK, 4 rows affected (0.00 sec)
    19 Records: 4  Duplicates: 0  Warnings: 0
    20 
    21 mysql> insert into xxb(age) values(10), (11), (12), (13);
    22 Query OK, 4 rows affected (0.00 sec)
    23 Records: 4  Duplicates: 0  Warnings: 0

    left join:

     1 mysql> select * from xxa left join xxb on xxa.id = xxb.id;
     2 +----+------+------+------+
     3 | id | name | id   | age  |
     4 +----+------+------+------+
     5 |  1 | xxj  |    1 |   10 |
     6 |  2 | xxa  |    2 |   11 |
     7 |  3 | xxb  |    3 |   12 |
     8 |  4 | xxc  |    4 |   13 |
     9 |  5 | xxd  | NULL | NULL |
    10 +----+------+------+------+
    11 5 rows in set (0.00 sec)

    right join:

     1 mysql> select * from xxa right join xxb on xxa.id = xxb.id;
     2 +------+------+----+------+
     3 | id   | name | id | age  |
     4 +------+------+----+------+
     5 |    1 | xxj  |  1 |   10 |
     6 |    2 | xxa  |  2 |   11 |
     7 |    3 | xxb  |  3 |   12 |
     8 |    4 | xxc  |  4 |   13 |
     9 | NULL | NULL |  8 |   14 |
    10 +------+------+----+------+
    11 5 rows in set (0.00 sec)

    inner join:

     1 mysql> select * from xxa, xxb where xxa.id = xxb.id;
     2 +----+------+----+------+
     3 | id | name | id | age  |
     4 +----+------+----+------+
     5 |  1 | xxj  |  1 |   10 |
     6 |  2 | xxa  |  2 |   11 |
     7 |  3 | xxb  |  3 |   12 |
     8 |  4 | xxc  |  4 |   13 |
     9 +----+------+----+------+
    10 4 rows in set (0.00 sec)

    limit:

    1 mysql> select * from xxa, xxb where xxa.id = xxb.id limit 2, 3;
    2 +----+------+----+------+
    3 | id | name | id | age  |
    4 +----+------+----+------+
    5 |  3 | xxb  |  3 |   12 |
    6 |  4 | xxc  |  4 |   13 |
    7 +----+------+----+------+
    8 2 rows in set (0.00 sec)

    limit 有两个参数,第一个是偏移量(从0开始),第二个是返回结果数目。

    limit n相当于limit 0, n。

    存储过程:

     1 mysql> delimiter $
     2 mysql> create procedure test(in p int) begin  insert into xxb(age) values(p); end$
     3 Query OK, 0 rows affected (0.00 sec)
     4 
     5 mysql> delimiter ;
     6 mysql> call test(100);
     7 Query OK, 1 row affected (0.02 sec)
     8 
     9 mysql> select * from xxb;
    10 +----+------+
    11 | id | age  |
    12 +----+------+
    13 |  1 |   10 |
    14 |  2 |   11 |
    15 |  3 |   12 |
    16 |  4 |   13 |
    17 |  5 |   22 |
    18 |  6 |   55 |
    19 |  7 |  100 |
    20 +----+------+
    21 7 rows in set (0.00 sec)

    这里一开始要用delimiter $修改一下结束符为$,这样才能在终端写存储过程,创建好存储过程之后再改回来就行。

     1 mysql> show procedure status;
     2 +-----+------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+
     3 | Db  | Name | Type      | Definer        | Modified            | Created             | Security_type | Comment | character_set_client | collation_connection | Database Collation |
     4 +-----+------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+
     5 | xxj | a    | PROCEDURE | root@localhost | 2014-10-09 11:51:09 | 2014-10-09 11:51:09 | DEFINER       |         | utf8                 | utf8_general_ci      | latin1_swedish_ci  |
     6 | xxj | b    | PROCEDURE | root@localhost | 2014-10-09 12:01:21 | 2014-10-09 12:01:21 | DEFINER       |         | utf8                 | utf8_general_ci      | latin1_swedish_ci  |
     7 | xxj | test | PROCEDURE | root@localhost | 2014-10-09 12:02:42 | 2014-10-09 12:02:42 | DEFINER       |         | utf8                 | utf8_general_ci      | latin1_swedish_ci  |
     8 +-----+------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+
     9 3 rows in set (0.00 sec)
    10 
    11 mysql> drop procedure a;
    12 Query OK, 0 rows affected (0.02 sec)

    使用存储过程的好处:

    • 减少了服务器/客户端网络流量
      • 过程中的命令作为代码的单个批处理执行。 这可以显著减少服务器和客户端之间的网络流量,因为只有对执行过程的调用才会跨网络发送。 如果没有过程提供的代码封装,每个单独的代码行都不得不跨网络发送。
    • 更强的安全性
      • 多个用户和客户端程序可以通过过程对基础数据库对象执行操作,即使用户和程序对这些基础对象没有直接权限。 过程控制执行哪些进程和活动,并且保护基础数据库对象。 这消除在了单独的对象级别授予权限的要求,并且简化了安全层。
    • 代码的重复使用
      • 任何重复的数据库操作的代码都非常适合于在过程中进行封装。 这消除了不必要地重复编写相同的代码、降低了代码不一致性,并且允许拥有所需权限的任何用户或应用程序访问和执行代码。
    • 更容易维护
      • 在客户端应用程序调用过程并且将数据库操作保持在数据层中时,对于基础数据库中的任何更改,只有过程是必须更新的。
      • 应用程序层保持独立,并且不必知道对数据库布局、关系或进程的任何更改的情况。
    • 改进的性能
      • 默认情况下,在首次执行过程时将编译过程,并且创建一个执行计划,供以后的执行重复使用。 因为查询处理器不必创建新计划,所以,它通常用更少的时间来处理过程。
      • 如果过程引用的表或数据有显著变化,则预编译的计划可能实际上会导致过程的执行速度减慢。 在此情况下,重新编译过程和强制新的执行计划可提高性能。

    查看当前状态

     1 mysql> show processlist;
     2 +----+------+-----------+------+---------+------+-------+------------------+
     3 | Id | User | Host      | db   | Command | Time | State | Info             |
     4 +----+------+-----------+------+---------+------+-------+------------------+
     5 | 47 | root | localhost | xxj  | Query   |    0 | init  | show processlist |
     6 +----+------+-----------+------+---------+------+-------+------------------+
     7 1 row in set (0.00 sec)
     8 mysql> show status like '%aborted%';
     9 +------------------+-------+
    10 | Variable_name    | Value |
    11 +------------------+-------+
    12 | Aborted_clients  | 0     |
    13 | Aborted_connects | 1     |
    14 +------------------+-------+
    15 2 rows in set (0.00 sec)
    16 
    17 mysql> show variables like '%connection%';
    18 +--------------------------+-----------------+
    19 | Variable_name            | Value           |
    20 +--------------------------+-----------------+
    21 | character_set_connection | utf8            |
    22 | collation_connection     | utf8_general_ci |
    23 | max_connections          | 151             |
    24 | max_user_connections     | 0               |
    25 +--------------------------+-----------------+
    26 4 rows in set (0.03 sec)

    或者:

     1 root@xxj-VirtualBox:~# mysqladmin -uroot -p processlist
     2 Enter password: 
     3 +----+------+-----------+----+---------+------+-------+------------------+
     4 | Id | User | Host      | db | Command | Time | State | Info             |
     5 +----+------+-----------+----+---------+------+-------+------------------+
     6 | 48 | root | localhost |    | Query   | 0    | init  | show processlist |
     7 +----+------+-----------+----+---------+------+-------+------------------+
     8 root@xxj-VirtualBox:~# mysqladmin -uroot -p status
     9 Enter password: 
    10 Uptime: 354349  Threads: 1  Questions: 205  Slow queries: 0  Opens: 335  Flush tables: 1  Open tables: 83  Queries per second avg: 0.000

    变量可以通过配置文件my.conf来修改。当连接请求大于默认连接数后,就会出现无法连接数据库的错误。

    索引

    Most MySQL indexes (PRIMARY KEY, UNIQUE, INDEX, and FULLTEXT) are stored in B-trees. Exceptions are that indexes on spatial data types use R-trees, and that MEMORY tables also support hash indexes.

    A B-tree index can be used for column comparisons in expressions that use the =, >, >=, <, <=, or BETWEEN operators. The index also can be used for LIKE comparisons if the argument to LIKE is a constant string that does not start with a wildcard character. 

    B树索引可以用于查找、排序、求最大最小值、范围查询等。

    hash索引只能用于作=或者<=或者>=查找,不能用作<或>查找。

    • They are used only for equality comparisons that use the = or <=> operators (but are very fast). They are not used for comparison operators such as < that find a range of values.
    • The optimizer cannot use a hash index to speed up ORDER BY operations. (This type of index cannot be used to search for the next entry in order.)
    • MySQL cannot determine approximately how many rows there are between two values (this is used by the range optimizer to decide which index to use). This may affect some queries if you change a MyISAM table to a hash-indexed MEMORY table.
    • Only whole keys can be used to search for a row. (With a B-tree index, any leftmost prefix of the key can be used to find rows.)

    部分摘自:http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html

    http://blog.codinglabs.org/articles/theory-of-mysql-index.html 这一篇提到mysql实际是用B+树(myisam和innodb引擎都是)。估计官网所说的B-tree,其实指的是B+树吧,毕竟B+树也是B树的一个变种。 

    为了进行高效查询,可以在数据表上针对某一字段建立索引,由于该索引包括了一个指向数据的指针,数据库服务器则只沿着索引排列的顺序对仅有一列数据的索引进行读取(只建立一个索引)直至索引指针指向相应的记录上为止。由于索引只是按照一个字段进行查找,而没有对整表进行遍历,因此一般说来索引查找比全表扫描的速度快。
    那么,是不是使用索引查询一定比全表扫描的速度快呢?答案是否定的。如果查询小型数据表(记录很少)或是查询大型数据表(记录很多)的绝大部分数据,全表扫描更为实用。例如,查询“性别”字段,其值只能是“男或女”,在其上建立索引的意义就不大,甚至不允许在布尔型、大二进制型(备注型、图像型等)上建立索引。

    1.聚集索引

    其实,我们的汉语字典的正文本身就是一个聚集索引。比如,我们要查“安”字,就会很自然地翻开字典的前几页,因为“安”的拼音是an, 字典的正文部分本身就是一个目录,您不需要再去查其他目录来找到您需要找的内容。
    我们把这种正文内容本身就是一种按照一定规则排列的目录称为“聚集索引”。

    2.非聚集索引

    如果您认识某个字,您可以快速地从自动中查到这个字。但您也可能会遇到您不认识的字,不知道它的发音,这时候,您就不能按照刚才的方法找到您要查的字,而需要去根据“偏旁部首”查到您要找的字,然后根据这个字后的页码直接翻到某页来找到您要找的字。但您结合“部首目录”和“检字表”而查到的字的排序并不是真正的正文的排序方法,比如您查“张”字,我们可以看到在查部首之后的检字表中“张”的页码是672页,检字表中“张”的上面是“驰”字,但页码却是63页,“张”的下面是“弩”字,页面是390页。很显然,这些字并不是真正的分别位于“张”字的上下方,现在您看到的连续的“驰、张、弩”三字实际上就是他们在非聚集索引中的排序,是字典正文中的字在非聚集索引中的映射。我们可以通过这种方式来找到您所需要的字,但它需要两个过程,先找到目录中的结果,然后再翻到您所需要的页码。
    我们把这种目录纯粹是目录,正文纯粹是正文的排序方式称为“非聚集索引”。

    非聚集索引可以建多个,具有B树结构,其叶级节点不包含数据页,只包含索引行。

    聚集索引中,数据所在的数据页是叶级,索引数据所在的索引页是非叶级。聚集索引在任何一种数据表中只能建立一个;并且建立聚集索引需要至少相当于源表120%的附加空间,以存放源表的副本和索引中间页。
    在只建立了非聚集索引的情况下,每个叶级节点指明了记录的行定位符(RID);而在既有聚集索引又有非聚集索引的情况下,每个叶级节点所指向的是该聚集索引的索引键值,即数据记录本身。
    当数据发生更新的时候,SQLS只负责对聚集索引的键值加以维护,而不必考虑非聚集索引。只要我们在ID类的字段上建立聚集索引,而在其它经常需要查询的字段上建立非聚集索引,通过这种科学的、有针对性的在一张表上分别建立聚集索引和非聚集索引的方法,我们既享受了索引带来的灵活与快捷,又相对避免了维护索引所导致的大量的额外资源消耗。

    索引有一些先天不足:
    1、系统要占用大约为表的1.2倍的硬盘和内存空间来保存索引;
    2、更新数据的时候,系统必须要有额外的时间来同时对索引进行更新,以维持数据和索引的一致性。
    在如下字段建立索引应该是不恰当的:
    1、很少或从不引用的字段;
    2、逻辑型的字段,如男或女(是或否)等。

    clustered和nonclustered是ms sql里面的概念;mysql不太一样。

    When you define a PRIMARY KEY on your table, InnoDB uses it as the clustered index. Define a primary key for each table that you create.

    If you do not define a PRIMARY KEY for your table, MySQL locates the first UNIQUE index where all the key columns are NOT NULL and InnoDB uses it as the clustered index.

    If the table has no PRIMARY KEY or suitable UNIQUE index, InnoDB internally generates a hidden clustered index on a synthetic column containing row ID values. The rows are ordered by the ID that InnoDB assigns to the rows in such a table.

    Accessing a row through the clustered index is fast because the index search leads directly to the page with all the row data. If a table is large, the clustered index architecture often saves a disk I/O operation when compared to storage organizations that store row data using a different page from the index record. (For example, MyISAM uses one file for data rows and another for index records.)

    If you are using the 'MyISAM' engine, no index (not even PRIMARY KEY) is 'clustered'. If you are using InnoDB, the PRIMARY KEY is always clustered, no choice. Secondary indexes are never clustered, no choice.

     1 mysql> show create table xxa;
     2 +-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
     3 | Table | Create Table                                                                                                                                                                 |
     4 +-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
     5 | xxa   | CREATE TABLE `xxa` (
     6   `id` int(11) NOT NULL AUTO_INCREMENT,
     7   `name` varchar(20) DEFAULT NULL,
     8   PRIMARY KEY (`id`)
     9 ) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=latin1 |
    10 +-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    11 1 row in set (0.00 sec)

    Since the data is part of the index that sorted and deliberately fragmented, it is obvious that only one cluster key can be used for a single table. Also, there is one more important consequence, namely they are the write operations, and especially changing the key fields in existing data. It is extremely resource-intensive process. Try to use rarely changed fields for the clustered indexes.

    1 mysql> create index name_index on xxa(name);
    2 Query OK, 5 rows affected (0.01 sec)
    3 Records: 5  Duplicates: 0  Warnings: 0
    4 
    5 mysql> drop index name_index;
    6 ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
    7 mysql> drop index name_index on xxa;
    8 Query OK, 5 rows affected (0.01 sec)
    9 Records: 5  Duplicates: 0  Warnings: 0

    视图

     1 mysql> create or replace view v as select name from xxa;
     2 Query OK, 0 rows affected (0.00 sec)
     3 
     4 mysql> select * from v;
     5 +------+
     6 | name |
     7 +------+
     8 | xxj  |
     9 | xxa  |
    10 | xxb  |
    11 | xxc  |
    12 | xxd  |
    13 +------+
    14 5 rows in set (0.01 sec)

    使用视图的理由是什么?
    1.安全性。一般是这样做的:创建一个视图,定义好该视图所操作的数据。之后将用户权限与视图绑定。这样的方式是使用到了一个特性:grant语句可以针对视图进行授予权限。
    2.查询性能提高。
    3.有灵活性的功能需求后,需要改动表的结构而导致工作量比较大。那么可以使用虚拟表的形式达到少修改的效果。这是在实际开发中比较有用的。

    例子:假如因为某种需要,a表与b表需要进行合并起来组成一个新的表c。最后a表与b表都不会存在了。而由于原来程序中编写sql分别是基于a表与b表查询的,这就意味着需要重新编写大量的sql(改成向c表去操作数据)。而通过视图就可以做到不修改。定义两个视图名字还是原来的表名a和b。a、b视图完成从c表中取出内容。
    说明:使用这样的解决方式,基于对视图的细节了解越详细越好。因为使用视图还是与使用表的语法上没区别。比如视图名a,那么查询还是"select * from a"。

    4.复杂的查询需求。可以进行问题分解,然后将创建多个视图获取数据。将视图联合起来就能得到需要的结果了。

    视图的工作机制:当调用视图的时候,才会执行视图中的sql,进行取数据操作。视图的内容没有存储,而是在视图被引用的时候才派生出数据。这样不会占用空间,由于是即时引用,视图的内容总是与真实表的内容是一致的。
    视图这样设计有什么好处?节省空间,内容是总是一致的话,那么我们不需要维护视图的内容,维护好真实表的内容,就可以保证视图的完整性了。

    对于可更新视图,可给定WITH CHECK OPTION子句来防止插入或更新行,除非作用在行上的select_statement中的WHERE子句为“真”。

    视图也是一种表,是虚拟表。不能与已有的表(视图)出现重名。

     1 mysql> update xxa set name = 'xxe';
     2 Query OK, 5 rows affected (0.00 sec)
     3 Rows matched: 5  Changed: 5  Warnings: 0
     4 
     5 mysql> select * from v;
     6 +------+
     7 | name |
     8 +------+
     9 | xxe  |
    10 | xxe  |
    11 | xxe  |
    12 | xxe  |
    13 | xxe  |
    14 +------+
    15 5 rows in set (0.00 sec)
    16 
    17 mysql> select * from xxa;
    18 +----+------+
    19 | id | name |
    20 +----+------+
    21 |  1 | xxe  |
    22 |  2 | xxe  |
    23 |  3 | xxe  |
    24 |  4 | xxe  |
    25 |  5 | xxe  |
    26 +----+------+
    27 5 rows in set (0.00 sec)
    28 
    29 mysql> update v set name = 'xxf';
    30 Query OK, 5 rows affected (0.00 sec)
    31 Rows matched: 5  Changed: 5  Warnings: 0
    32 
    33 mysql> select * from xxa;
    34 +----+------+
    35 | id | name |
    36 +----+------+
    37 |  1 | xxf  |
    38 |  2 | xxf  |
    39 |  3 | xxf  |
    40 |  4 | xxf  |
    41 |  5 | xxf  |
    42 +----+------+
    43 5 rows in set (0.00 sec)

    Storage Engine

    数据的大小,是一个影响你选择什么样存储引擎的重要因素,大尺寸的数据集趋向于选择InnoDB方式,因为其支持事务处理和故障恢复。数据库的大小决定了故障恢复的时间长短,InnoDB可以利用事务日志进行数据恢复,这会比较快。而MyISAM可能会需要几个小时甚至几天来干这些事,InnoDB只需要几分钟。

    您操作数据库表的习惯可能也会是一个对性能影响很大的因素。比如: COUNT() 在 MyISAM 表中会非常快,而在InnoDB 表下可能会很痛苦。而主键查询则在InnoDB下会相当相当的快,但需要小心的是如果我们的主键太长了也会导致性能问题。大批的inserts 语句在MyISAM下会快一些,但是updates 在InnoDB 下会更快一些——尤其在并发量大的时候。

    如果是一些小型的应用或项目,那么MyISAM 也许会更适合。当然,在大型的环境下使用MyISAM 也会有很大成功的时候,但却不总是这样的。如果你正在计划使用一个超大数据量的项目,而且需要事务处理或外键支持,那么你真的应该直接使用InnoDB方式。但需要记住InnoDB 的表需要更多的内存和存储,转换100GB 的MyISAM 表到InnoDB 表可能会让你有非常坏的体验。

    MyISAM类型不支持事务处理等高级处理,而InnoDB类型支持。MyISAM类型的表强调的是性能,其执行速度比InnoDB类型更快,但是不提供事务支持,而InnoDB提供事务支持已经外部键等高级数据库功能。

    以下是一些细节和具体实现的差别:

      ◆1.InnoDB不支持FULLTEXT类型的索引。

      ◆2.InnoDB 中不保存表的具体行数,也就是说,执行select count(*) from table时,InnoDB要扫描一遍整个表来计算有多少行,但是MyISAM只要简单的读出保存好的行数即可。注意的是,当count(*)语句包含 where条件时,两种表的操作是一样的。

      ◆3.对于AUTO_INCREMENT类型的字段,InnoDB中必须包含只有该字段的索引,但是在MyISAM表中,可以和其他字段一起建立联合索引。

      ◆4.DELETE FROM table时,InnoDB不会重新建立表,而是一行一行的删除。

      ◆5.LOAD TABLE FROM MASTER操作对InnoDB是不起作用的,解决方法是首先把InnoDB表改成MyISAM表,导入数据后再改成InnoDB表,但是对于使用的额外的InnoDB特性(例如外键)的表不适用。

      另外,InnoDB表的行锁也不是绝对的,假如在执行一个SQL语句时MySQL不能确定要扫描的范围,InnoDB表同样会锁全表,例如update table set num=1 where name like “%aaa%”

      两种类型最主要的差别就是Innodb 支持事务处理与外键和行级锁.而MyISAM不支持.所以MyISAM往往就容易被人认为只适合在小项目中使用。

      我作为使用MySQL的用户角度出发,Innodb和MyISAM都是比较喜欢的,但是从我目前运维的数据库平台要达到需求:99.9%的稳定性,方便的扩展性和高可用性来说的话,MyISAM绝对是我的首选。

      原因如下:

      1、首先我目前平台上承载的大部分项目是读多写少的项目,而MyISAM的读性能是比Innodb强不少的。

      2、MyISAM的索引和数据是分开的,并且索引是有压缩的,内存使用率就对应提高了不少。能加载更多索引,而Innodb是索引和数据是紧密捆绑的,没有使用压缩从而会造成Innodb比MyISAM体积庞大不小。

      3、从平台角度来说,经常隔1,2个月就会发生应用开发人员不小心update一个表where写的范围不对,导致这个表没法正常用了,这个时候MyISAM的优越性就体现出来了,随便从当天拷贝的压缩包取出对应表的文件,随便放到一个数据库目录下,然后dump成sql再导回到主库,并把对应的binlog补上。如果是Innodb,恐怕不可能有这么快速度,别和我说让Innodb定期用导出xxx.sql机制备份,因为我平台上最小的一个数据库实例的数据量基本都是几十G大小。

      4、从我接触的应用逻辑来说,select count(*) 和order by 是最频繁的,大概能占了整个sql总语句的60%以上的操作,而这种操作Innodb其实也是会锁表的,很多人以为Innodb是行级锁,那个只是where对它主键是有效,非主键的都会锁全表的。

      5、还有就是经常有很多应用部门需要我给他们定期某些表的数据,MyISAM的话很方便,只要发给他们对应那表的frm.MYD,MYI的文件,让他们自己在对应版本的数据库启动就行,而Innodb就需要导出xxx.sql了,因为光给别人文件,受字典数据文件的影响,对方是无法使用的。

      6、如果和MyISAM比insert写操作的话,Innodb还达不到MyISAM的写性能,如果是针对基于索引的update操作,虽然MyISAM可能会逊色Innodb,但是那么高并发的写,从库能否追的上也是一个问题,还不如通过多实例分库分表架构来解决。

      7、如果是用MyISAM的话,merge引擎可以大大加快应用部门的开发速度,他们只要对这个merge表做一些select count(*)操作,非常适合大项目总量约几亿的rows某一类型(如日志,调查统计)的业务表。

      当然Innodb也不是绝对不用,用事务的项目如模拟炒股项目,我就是用Innodb的,活跃用户20多万时候,也是很轻松应付了,因此我个人也是很喜欢Innodb的,只是如果从数据库平台应用出发,我还是会首选MyISAM。

      另外,可能有人会说你MyISAM无法抗太多写操作,但是我可以通过架构来弥补,说个我现有用的数据库平台容量:主从数据总量在几百T以上,每天十多亿 pv的动态页面,还有几个大项目是通过数据接口方式调用未算进pv总数,(其中包括一个大项目因为初期memcached没部署,导致单台数据库每天处理 9千万的查询)。而我的整体数据库服务器平均负载都在0.5-1左右。

    这一部分节选自:http://www.php100.com/html/webkaifa/database/Mysql/2011/0326/7789.html

    建立用户

    1 mysql> insert into user(Host, User, Password) values("localhost", "xxj", password("123456"));
    2 mysql> flush privileges;

    不同用户创建的库默认是不能相互看到的。要给权限;

    1 mysql> grant select on xxj.* to xxj@'localhost' identified by '123456' with grant option;
    2 Query OK, 0 rows affected (0.00 sec)
    1 mysql> show grants;
    2 +------------------------------------------------------------------------------------------------------------+
    3 | Grants for xxj@localhost                                                                                   |
    4 +------------------------------------------------------------------------------------------------------------+
    5 | GRANT USAGE ON *.* TO 'xxj'@'localhost' IDENTIFIED BY PASSWORD '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9' |
    6 | GRANT SELECT ON `xxj`.* TO 'xxj'@'localhost' WITH GRANT OPTION                                             |
    7 +------------------------------------------------------------------------------------------------------------+
    8 2 rows in set (0.00 sec)

    删除权限:

    mysql> revoke select on xxj.* from 'xxj'@'localhost';
    Query OK, 0 rows affected (0.00 sec)

    删除权限后再执行的错误是没有权限,而不是表不存在;

    1 mysql> select * from test;
    2 ERROR 1142 (42000): SELECT command denied to user 'xxj'@'localhost' for table 'test'
  • 相关阅读:
    寒假周总结一
    1657. Determine if Two Strings Are Close
    1656. Design an Ordered Stream
    695. Max Area of Island (BFS)
    695. Max Area of Island (DFS)
    Daily Coding Problem: Problem #713
    939. Minimum Area Rectangle
    259. 3Sum Smaller
    29. Divide Two Integers
    16. 3Sum Closest
  • 原文地址:https://www.cnblogs.com/linyx/p/3830625.html
Copyright © 2011-2022 走看看