`
lobin
  • 浏览: 417891 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

mysql

 
阅读更多

 

初始化

$ ./bin/mysqld --initialize --user=mysql --datadir=/tmp/mysql-5.7.37-linux-glibc2.12-x86_64/data

2023-03-19T15:50:25.064795Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).

2023-03-19T15:50:25.064882Z 0 [ERROR] Can't find error-message file '/usr/local/mysql/share/errmsg.sys'. Check error-message file location and 'lc-messages-dir' configuration directive.

2023-03-19T15:50:25.944817Z 0 [Warning] InnoDB: New log files created, LSN=45790

2023-03-19T15:50:26.059737Z 0 [Warning] InnoDB: Creating foreign key constraint system tables.

2023-03-19T15:50:26.125012Z 0 [Warning] No existing UUID has been found, so we assume that this is the first time that this server has been started. Generating a new UUID: c40c9ffa-c66d-11ed-9ab2-00163e145f5c.

2023-03-19T15:50:26.125897Z 0 [Warning] Gtid table is not ready to be used. Table 'mysql.gtid_executed' cannot be opened.

2023-03-19T15:50:27.091304Z 0 [Warning] 

2023-03-19T15:50:27.091351Z 0 [Warning] 

2023-03-19T15:50:27.091982Z 0 [Warning] CA certificate ca.pem is self signed.

 

修改root密码

$ ./bin/mysqladmin --user=root -p password

Enter password: 

New password: 

Confirm new password: 

Warning: Since password will be sent to server in plain text, use ssl connection to ensure password safety.

 

mysql配置

 

Default options are read from the following files in the given order:

 

/etc/my.cnf /etc/mysql/my.cnf /usr/local/mysql/etc/my.cnf ~/.my.cnf

 

以上提示信息可以通过./mysqld --verbose --help命令看到。

 

配置文件

 

[mysqld]

#

# Remove leading # and set to the amount of RAM for the most important data

# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.

# innodb_buffer_pool_size = 128M

#

# Remove the leading "# " to disable binary logging

# Binary logging captures changes between backups and is enabled by

# default. It's default setting is log_bin=binlog

# disable_log_bin

#

# Remove leading # to set options mainly useful for reporting servers.

# The server defaults are faster for transactions and fast SELECTs.

# Adjust sizes as needed, experiment to find the optimal values.

# join_buffer_size = 128M

# sort_buffer_size = 2M

# read_rnd_buffer_size = 2M

#

# Remove leading # to revert to previous value for default_authentication_plugin,

# this will increase compatibility with older clients. For background, see:

# https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_default_authentication_plugin

# default-authentication-plugin=mysql_native_password

 

datadir=/var/lib/mysql

socket=/var/lib/mysql/mysql.sock

 

log-error=/var/log/mysqld.log

pid-file=/var/run/mysqld/mysqld.pid

 

启动

# mysqld --user=mysql &

# ps -ef | grep mysql

mysql     4269  3242 33 15:23 pts/1    00:00:31 mysqld --user=mysql

# netstat -anop | grep 3306

tcp        0      0 :::3306                     :::*                        LISTEN      4269/mysqld         off (0.00/0/0)

tcp        0      0 :::33060                    :::*                        LISTEN      4269/mysqld         off (0.00/0/0)

 

# mysqld_safe --user=mysql &

# ps -ef | grep mysql

root      4342  3242  1 15:25 pts/1    00:00:00 /bin/sh /usr/bin/mysqld_safe --user=mysql

mysql     4471  4342 37 15:26 pts/1    00:00:28 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib/mysql/plugin --user=mysql --log-error=/var/log/mysqld.log --pid-file=/var/run/mysqld/mysqld.pid --socket=/var/lib/mysql/mysql.sock

 

mysql启动的时候,参数选项还有顺序的限制。如--defaults-file

 

$ sudo ./bin/mysqld_safe --user=mysql --defaults-file=./my.cnf 

Logging to '/usr/local/mysql/data/admindeMacBook-Air.local.err'.

2022-05-24T12:36:47.6NZ mysqld_safe Starting mysqld daemon with databases from /usr/local/mysql/data

 

2022-05-24T12:36:49.6NZ mysqld_safe mysqld from pid file /usr/local/mysql/data/admindeMacBook-Air.local.pid ended

这里在启动的时候--defaults-file放在最后的话,mysql启动失败:

2022-05-24T12:32:58.323297Z 0 [ERROR] unknown variable 'defaults-file=./my.cnf'

 

2022-05-24T12:32:58.323319Z 0 [ERROR] Aborting

 

将--defaults-file选项放在前面的话,就可以启动起来了:

 

$ sudo ./bin/mysqld_safe --defaults-file=./my.cnf --user=mysql

 

# netstat -anop | grep 3306

tcp        0      0 :::3306                     :::*                        LISTEN      4471/mysqld         off (0.00/0/0)

tcp        0      0 :::33060                    :::*                        LISTEN      4471/mysqld         off (0.00/0/0)

 

连接

客户端连接mysql的时候需要指定正确的字符集,如果字符集不正确的话,将会出现乱码。这在包含中文的时候经常出现乱码。

 

包括在使用MySQL C API连接mysql的时候,尤其需要自己手动指定这个字符集:

 set names utf8

 可以向mysql服务器发送以下请求:

char *sql = "set names utf8";

mysql_query(mysql, sql); 

 

mysql> CREATE USER 'root'@'%' IDENTIFIED BY '**********';

Query OK, 0 rows affected (0.19 sec)

 

mysql> GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;

Query OK, 0 rows affected (0.33 sec)

 

或者

mysql> GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'jxcoco1128' WITH GRANT OPTION;

Query OK, 0 rows affected, 1 warning (0.06 sec)

 

查看事务是否自动提交

show variables like 'autocommit';

 

查询事务隔离级别

show variables like 'tx_isolation';

 

查看是否开启General Log(general_log)

show variables like 'general_log';

 

开启General Log(general_log)

set global general_log=on;

 

查看General Log(general_log)日志文件存放路径

show variables like 'general_log_file';

 

建表

 

alter table post character set utf8;

alter table post modify column id varchar(32) character set utf8 not null;

 

插入

 

删除

 

更新

 

查询

 

查询效率

写出查询sql很容易,但要写出高效的查询sql就不是那么容易的。

提升查询效率

1、索引

索引是提升查询sql效率最常见也是最有效的途径

2、sql语句缓存

3、查询缓存

 

一个特殊的查询例子:

以下查询的apn_user表中,username字段是varchar类型,该字段的值可以是数字字符串,但在查询时,如果查询子句的字段值使用的数字部分,也可以查到:

mysql> select * from apn_user where username = 111;

+----+---------------------+---------------+------+----------+--------------+----------+

| id | created_date        | email         | name | password | updated_date | username |

+----+---------------------+---------------+------+----------+--------------+----------+

|  1 | 2012-01-20 12:12:12 | 111@gmail.com | 111  | 111      | NULL         | 111aaa   |

+----+---------------------+---------------+------+----------+--------------+----------+

1 row in set (0.00 sec)

 

mysql> explain select * from apn_user where username = 111;

+----+-------------+----------+------+---------------+------+---------+------+------+-------------+

| id | select_type | table    | type | possible_keys | key  | key_len | ref  | rows | Extra       |

+----+-------------+----------+------+---------------+------+---------+------+------+-------------+

|  1 | SIMPLE      | apn_user | ALL  | username      | NULL | NULL    | NULL |    5 | Using where |

+----+-------------+----------+------+---------------+------+---------+------+------+-------------+

1 row in set (0.00 sec)

但如果查询子句的字段建了索引, 查询时索引无效。

 

 

索引

 

创建索引

语法:

 

CREATE [UNIQUE | FULLTEXT | SPATIAL] INDEX index_name
    [index_type]
    ON tbl_name (key_part,...)
    [index_option]
    [algorithm_option | lock_option] ...

key_part: {col_name [(length)] | (expr)} [ASC | DESC]

index_option:
    KEY_BLOCK_SIZE [=] value
  | index_type
  | WITH PARSER parser_name
  | COMMENT 'string'
  | {VISIBLE | INVISIBLE}

index_type:
    USING {BTREE | HASH}

algorithm_option:
    ALGORITHM [=] {DEFAULT | INPLACE | COPY}

lock_option:
    LOCK [=] {DEFAULT | NONE | SHARED | EXCLUSIVE}
 

索引可以创建普通索引,唯一索引,FULLTEXT全文索引,SPATIAL索引

 

创建普通索引

mysql> create index idx_updated_date on apn_user(updated_date);

Query OK, 5 rows affected (0.23 sec)

Records: 5  Duplicates: 0  Warnings: 0

 

mysql> show index from apn_user;

+----------+------------+------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+

| Table    | Non_unique | Key_name         | Seq_in_index | Column_name  | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |

+----------+------------+------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+

| apn_user |          1 | idx_updated_date |            1 | updated_date | A         |           2 |     NULL | NULL   | YES  | BTREE      |         |

+----------+------------+------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+

 

创建唯一索引

mysql> create unique index idx_updated_date on apn_user(updated_date);

Query OK, 5 rows affected (0.25 sec)

Records: 5  Duplicates: 0  Warnings: 0

mysql> show index from apn_user;

+----------+------------+------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+

| Table    | Non_unique | Key_name         | Seq_in_index | Column_name  | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |

+----------+------------+------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+

| apn_user |          0 | idx_updated_date |            1 | updated_date | A         |           2 |     NULL | NULL   | YES  | BTREE      |         |

+----------+------------+------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+

 

mysql> alter table apn_user add unique idx_updated_date(updated_date);

Query OK, 5 rows affected (0.20 sec)

Records: 5  Duplicates: 0  Warnings: 0

mysql> show index from apn_user;

+----------+------------+------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+

| Table    | Non_unique | Key_name         | Seq_in_index | Column_name  | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |

+----------+------------+------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+

| apn_user |          0 | idx_updated_date |            1 | updated_date | A         |           2 |     NULL | NULL   | YES  | BTREE      |         |

+----------+------------+------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+

 

 

查看索引

mysql> show index from apn_user;

+----------+------------+------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+

| Table    | Non_unique | Key_name         | Seq_in_index | Column_name  | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |

+----------+------------+------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+

| apn_user |          0 | PRIMARY          |            1 | id           | A         |           2 |     NULL | NULL   |      | BTREE      |         |

| apn_user |          0 | username         |            1 | username     | A         |           2 |     NULL | NULL   |      | BTREE      |         |

| apn_user |          0 | idx_updated_date |            1 | updated_date | A         |           2 |     NULL | NULL   | YES  | BTREE      |         |

+----------+------------+------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+

3 rows in set (0.00 sec)

 

 

删除索引

mysql> drop index idx_updated_date on apn_user;

Query OK, 9 rows affected (0.27 sec)

Records: 9  Duplicates: 0  Warnings: 0

 

mysql> alter table apn_user drop key idx_updated_date;

Query OK, 5 rows affected (0.25 sec)

Records: 5  Duplicates: 0  Warnings: 0

 

索引类型

1、B树索引

BTREE

2、哈希索引

HASH

 

 

使用索引

索引不是直接用的,而是在检索数据的时候间接使用索引。

 

 

 

 

 

当然,即使在查询时在查询子句上对应的字段上建好了索引,在查询时也不一定会使用到索引,如果确定使用对应索引的确能提升查询的效率,可以强制使用索引。

 

强制使用索引

select * from <table> force index(<index name>, ...) where ...;

 

在使用强制使用索引时,得在有可能使用到索引的情况下才能使用索引。是否有可能使用到索引,可执行查询计划,如果查询计划结果中有“possible_keys”,就表示有可能使用到索引,可强制使用索引。

 

如下,强制使用索引是没用的:

mysql> select * from apn_user where username like '%aaa';

+----+---------------------+------------------+------+----------+--------------+----------+

| id | created_date        | email            | name | password | updated_date | username |

+----+---------------------+------------------+------+----------+--------------+----------+

|  1 | 2012-01-20 12:12:12 | 111@gmail.com    | 111  | 111      | NULL         | 111aaa   |

|  2 | 2012-01-21 12:12:12 | 222@yahoo.com.cn | 222  | 222      | NULL         | 222aaa   |

|  3 | 2012-02-08 18:01:43 | NULL             | NULL | 333      | NULL         | 333aaa   |

+----+---------------------+------------------+------+----------+--------------+----------+

3 rows in set (0.00 sec)

 

mysql> explain select * from apn_user where username like '%aaa';

+----+-------------+----------+------+---------------+------+---------+------+------+-------------+

| id | select_type | table    | type | possible_keys | key  | key_len | ref  | rows | Extra       |

+----+-------------+----------+------+---------------+------+---------+------+------+-------------+

|  1 | SIMPLE      | apn_user | ALL  | NULL          | NULL | NULL    | NULL |    5 | Using where |

+----+-------------+----------+------+---------------+------+---------+------+------+-------------+

1 row in set (0.01 sec)

从这里看,没有使用到索引,也没有可能使用到的索引“possible_keys”。

 

如果强制使用索引的话,也是无效的:

mysql> explain select * from apn_user force index(username) where username like '%aaa';

+----+-------------+----------+------+---------------+------+---------+------+------+-------------+

| id | select_type | table    | type | possible_keys | key  | key_len | ref  | rows | Extra       |

+----+-------------+----------+------+---------------+------+---------+------+------+-------------+

|  1 | SIMPLE      | apn_user | ALL  | NULL          | NULL | NULL    | NULL |    5 | Using where |

+----+-------------+----------+------+---------------+------+---------+------+------+-------------+

1 row in set (0.00 sec)

 

 

SQL执行计划

explain <查询>

 

SQL执行计划结果

Column        JSON NameMeaning

id        select_idThe SELECT identifier

select_typeNone        The SELECT type

table        table_nameThe table for the output row

partitionspartitionsThe matching partitions

type        access_typeThe join type

possible_keyspossible_keysThe possible indexes to choose

key        key        The index actually chosen

key_len        key_lengthThe length of the chosen key

ref        ref        The columns compared to the index

rows        rows        Estimate of rows to be examined

filteredfilteredPercentage of rows filtered by table condition

Extra        None        Additional information

 

查询sql中有几次查询,在SQL执行计划结果中就有几行。

 

列说明

5、type

 

system

 

The table has only one row (= system table). This is a special case of the const join type.

 

 

const

 

The table has at most one matching row, which is read at the start of the query. Because there is only one row, values from the column in this row can be regarded as constants by the rest of the optimizer. const tables are very fast because they are read only once.

 

const is used when you compare all parts of a PRIMARY KEY or UNIQUE index to constant values. In the following queries, tbl_name can be used as a const table:

 

SELECT * FROM tbl_name WHERE primary_key=1;

 

SELECT * FROM tbl_name

  WHERE primary_key_part1=1 AND primary_key_part2=2;

 

 

eq_ref

 

One row is read from this table for each combination of rows from the previous tables. Other than the system and const types, this is the best possible join type. It is used when all parts of an index are used by the join and the index is a PRIMARY KEY or UNIQUE NOT NULL index.

 

eq_ref can be used for indexed columns that are compared using the = operator. The comparison value can be a constant or an expression that uses columns from tables that are read before this table. In the following examples, MySQL can use an eq_ref join to process ref_table:

 

SELECT * FROM ref_table,other_table

  WHERE ref_table.key_column=other_table.column;

 

SELECT * FROM ref_table,other_table

  WHERE ref_table.key_column_part1=other_table.column

  AND ref_table.key_column_part2=1;

 

 

ref

 

All rows with matching index values are read from this table for each combination of rows from the previous tables. ref is used if the join uses only a leftmost prefix of the key or if the key is not a PRIMARY KEY or UNIQUE index (in other words, if the join cannot select a single row based on the key value). If the key that is used matches only a few rows, this is a good join type.

 

ref can be used for indexed columns that are compared using the = or <=> operator. In the following examples, MySQL can use a ref join to process ref_table:

 

SELECT * FROM ref_table WHERE key_column=expr;

 

SELECT * FROM ref_table,other_table

  WHERE ref_table.key_column=other_table.column;

 

SELECT * FROM ref_table,other_table

  WHERE ref_table.key_column_part1=other_table.column

  AND ref_table.key_column_part2=1;

 

 

fulltext

 

The join is performed using a FULLTEXT index.

 

 

ref_or_null

 

This join type is like ref, but with the addition that MySQL does an extra search for rows that contain NULL values. This join type optimization is used most often in resolving subqueries. In the following examples, MySQL can use a ref_or_null join to process ref_table:

 

SELECT * FROM ref_table

  WHERE key_column=expr OR key_column IS NULL;

See Section 8.2.1.14, “IS NULL Optimization”.

 

 

index_merge

 

This join type indicates that the Index Merge optimization is used. In this case, the key column in the output row contains a list of indexes used, and key_len contains a list of the longest key parts for the indexes used. For more information, see Section 8.2.1.3, “Index Merge Optimization”.

 

 

unique_subquery

 

This type replaces eq_ref for some IN subqueries of the following form:

 

value IN (SELECT primary_key FROM single_table WHERE some_expr)

unique_subquery is just an index lookup function that replaces the subquery completely for better efficiency.

 

 

index_subquery

 

This join type is similar to unique_subquery. It replaces IN subqueries, but it works for nonunique indexes in subqueries of the following form:

 

value IN (SELECT key_column FROM single_table WHERE some_expr)

 

 

range

 

Only rows that are in a given range are retrieved, using an index to select the rows. The key column in the output row indicates which index is used. The key_len contains the longest key part that was used. The ref column is NULL for this type.

 

range can be used when a key column is compared to a constant using any of the =, <>, >, >=, <, <=, IS NULL, <=>, BETWEEN, LIKE, or IN() operators:

 

SELECT * FROM tbl_name

  WHERE key_column = 10;

 

SELECT * FROM tbl_name

  WHERE key_column BETWEEN 10 and 20;

 

SELECT * FROM tbl_name

  WHERE key_column IN (10,20,30);

 

SELECT * FROM tbl_name

  WHERE key_part1 = 10 AND key_part2 IN (10,20,30);

 

 

index

 

The index join type is the same as ALL, except that the index tree is scanned. This occurs two ways:

 

If the index is a covering index for the queries and can be used to satisfy all data required from the table, only the index tree is scanned. In this case, the Extra column says Using index. An index-only scan usually is faster than ALL because the size of the index usually is smaller than the table data.

 

A full table scan is performed using reads from the index to look up data rows in index order. Uses index does not appear in the Extra column.

 

MySQL can use this join type when the query uses only columns that are part of a single index.

 

 

ALL

 

A full table scan is done for each combination of rows from the previous tables. This is normally not good if the table is the first table not marked const, and usually very bad in all other cases. Normally, you can avoid ALL by adding indexes that enable row retrieval from the table based on constant values or column values from earlier tables.

 

 

 

mysql> explain select * from apn_user a left join apn_user_info b on a.username = b.username;

+----+-------------+-------+--------+---------------+-----------+---------+----------------------+------+-------+

| id | select_type | table | type   | possible_keys | key       | key_len | ref                  | rows | Extra |

+----+-------------+-------+--------+---------------+-----------+---------+----------------------+------+-------+

|  1 | SIMPLE      | a     | ALL    | NULL          | NULL      | NULL    | NULL                 |    9 |       |

|  1 | SIMPLE      | b     | eq_ref | NewIndex1     | NewIndex1 | 98      | androidpn.a.username |    1 |       |

+----+-------------+-------+--------+---------------+-----------+---------+----------------------+------+-------+

2 rows in set (0.00 sec)

 

mysql> explain select * from apn_user a left join apn_user_info b on a.username = b.username where a.updated_date is not null;

+----+-------------+-------+--------+------------------+------------------+---------+----------------------+------+-------------+

| id | select_type | table | type   | possible_keys    | key              | key_len | ref                  | rows | Extra       |

+----+-------------+-------+--------+------------------+------------------+---------+----------------------+------+-------------+

|  1 | SIMPLE      | a     | range  | idx_updated_date | idx_updated_date | 9       | NULL                 |    3 | Using where |

|  1 | SIMPLE      | b     | eq_ref | NewIndex1        | NewIndex1        | 98      | androidpn.a.username |    1 |             |

+----+-------------+-------+--------+------------------+------------------+---------+----------------------+------+-------------+

2 rows in set (0.00 sec)

 

 

mysql> explain select * from apn_user a, apn_user_info b where a.username = b.username and a.updated_date is not null;

+----+-------------+-------+--------+---------------------------+------------------+---------+----------------------+------+-------------+

| id | select_type | table | type   | possible_keys             | key              | key_len | ref                  | rows | Extra       |

+----+-------------+-------+--------+---------------------------+------------------+---------+----------------------+------+-------------+

|  1 | SIMPLE      | a     | range  | username,idx_updated_date | idx_updated_date | 9       | NULL                 |    3 | Using where |

|  1 | SIMPLE      | b     | eq_ref | NewIndex1                 | NewIndex1        | 98      | androidpn.a.username |    1 | Using where |

+----+-------------+-------+--------+---------------------------+------------------+---------+----------------------+------+-------------+

2 rows in set (0.00 sec)

 

 

 

查询与索引

查询使用索引,是为了提升查询效率的。

 

以apn_user为例,其中有5条记录,除了主键,我们在username字段上建了索引。

mysql> select * from apn_user;

+----+---------------------+------------------+------+----------+---------------------+----------+

| id | created_date        | email            | name | password | updated_date        | username |

+----+---------------------+------------------+------+----------+---------------------+----------+

|  1 | 2012-01-20 12:12:12 | 111@gmail.com    | 111  | 111      | NULL                | 111aaa   |

|  2 | 2012-01-21 12:12:12 | 222@yahoo.com.cn | 222  | 222      | NULL                | 222aaa   |

|  3 | 2012-02-08 18:01:43 | NULL             | NULL | 333      | NULL                | 333aaa   |

|  4 | 2012-02-08 18:24:39 | NULL             | NULL | 444      | NULL                | 444      |

|  5 | 2012-02-08 18:24:39 | 555@555.com      | 555  | 555      | 2012-02-08 18:24:39 | 555      |

+----+---------------------+------------------+------+----------+---------------------+----------+

5 rows in set (0.00 sec)

 

mysql> show index from apn_user;

+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+

| Table    | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |

+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+

| apn_user |          0 | PRIMARY  |            1 | id          | A         |           5 |     NULL | NULL   |      | BTREE      |         |

| apn_user |          0 | username |            1 | username    | A         |           5 |     NULL | NULL   |      | BTREE      |         |

+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+

2 rows in set (0.00 sec)

 

 

mysql> explain select * from apn_user where username = '111aaa';

+----+-------------+----------+-------+---------------+----------+---------+-------+------+-------+

| id | select_type | table    | type  | possible_keys | key      | key_len | ref   | rows | Extra |

+----+-------------+----------+-------+---------------+----------+---------+-------+------+-------+

|  1 | SIMPLE      | apn_user | const | username      | username | 194     | const |    1 |       |

+----+-------------+----------+-------+---------------+----------+---------+-------+------+-------+

1 row in set (0.00 sec)

从上面的查询优化看,是用上了索引,索引是生效的。

但是看下面的查询,和上面的查询相比,仅仅是将=换成了!=,但是,看下面的查询计划

mysql> explain select * from apn_user where username != '111aaa';

+----+-------------+----------+------+---------------+------+---------+------+------+-------------+

| id | select_type | table    | type | possible_keys | key  | key_len | ref  | rows | Extra       |

+----+-------------+----------+------+---------------+------+---------+------+------+-------------+

|  1 | SIMPLE      | apn_user | ALL  | username      | NULL | NULL    | NULL |    5 | Using where |

+----+-------------+----------+------+---------------+------+---------+------+------+-------------+

1 row in set (0.00 sec)

发现索引无效!

 

这里username字段是varchar类型,该字段的值可以是数字字符串,但在查询时,如果查询子句的字段值使用的数字,而没有像字符串那样使用引号(单引号或双引号),那么不使用索引。

mysql> select * from apn_user where username = 444;

+----+---------------------+-------+------+----------+--------------+----------+

| id | created_date        | email | name | password | updated_date | username |

+----+---------------------+-------+------+----------+--------------+----------+

|  4 | 2012-02-08 18:24:39 | NULL  | NULL | 444      | NULL         | 444      |

+----+---------------------+-------+------+----------+--------------+----------+

1 row in set (0.00 sec)

 

mysql> explain select * from apn_user where username = 444;

+----+-------------+----------+------+---------------+------+---------+------+------+-------------+

| id | select_type | table    | type | possible_keys | key  | key_len | ref  | rows | Extra       |

+----+-------------+----------+------+---------------+------+---------+------+------+-------------+

|  1 | SIMPLE      | apn_user | ALL  | username      | NULL | NULL    | NULL |    5 | Using where |

+----+-------------+----------+------+---------------+------+---------+------+------+-------------+

1 row in set (0.00 sec)

这里看,索引无效。

 

mysql> explain select * from apn_user where username = '111';

+----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------------------------------+

| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra                                               |

+----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------------------------------+

|  1 | SIMPLE      | NULL  | NULL | NULL          | NULL | NULL    | NULL | NULL | Impossible WHERE noticed after reading const tables |

+----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------------------------------+

1 row in set (0.00 sec)

 

关于“Impossible WHERE noticed after reading const tables”

执行查询优化,如果看到有这个,表示sql在实际查询时会执行全表扫描。即便我们在查询子句上建了索引。

如果在查询子句上建了索引,索引无效。

这在查询时,如果没有符合查询子句的记录,会出现这种情况。

 

mysql> explain select * from apn_user where username like '%aaa';

+----+-------------+----------+------+---------------+------+---------+------+------+-------------+

| id | select_type | table    | type | possible_keys | key  | key_len | ref  | rows | Extra       |

+----+-------------+----------+------+---------------+------+---------+------+------+-------------+

|  1 | SIMPLE      | apn_user | ALL  | NULL          | NULL | NULL    | NULL |    5 | Using where |

+----+-------------+----------+------+---------------+------+---------+------+------+-------------+

1 row in set (0.00 sec)

从上面的查询优化看,没有用上索引,索引无效。

 

mysql> explain select * from apn_user where username like '_11aaa';

+----+-------------+----------+------+---------------+------+---------+------+------+-------------+

| id | select_type | table    | type | possible_keys | key  | key_len | ref  | rows | Extra       |

+----+-------------+----------+------+---------------+------+---------+------+------+-------------+

|  1 | SIMPLE      | apn_user | ALL  | NULL          | NULL | NULL    | NULL |    5 | Using where |

+----+-------------+----------+------+---------------+------+---------+------+------+-------------+

1 row in set (0.00 sec)

从上面的查询优化看,没有用上索引,索引无效。

 

 

mysql> explain select * from apn_user where username like '111%';

+----+-------------+----------+-------+---------------+----------+---------+------+------+-------------+

| id | select_type | table    | type  | possible_keys | key      | key_len | ref  | rows | Extra       |

+----+-------------+----------+-------+---------------+----------+---------+------+------+-------------+

|  1 | SIMPLE      | apn_user | range | username      | username | 194     | NULL |    1 | Using where |

+----+-------------+----------+-------+---------------+----------+---------+------+------+-------------+

1 row in set (0.00 sec)

这里使用了索引。

 

查询子句使用like时,如果查询字段上建了索引,'%aaa','_11aaa'会使索引失效, 即like时是以通配符%,_开头的都会使索引无效,'111%'这种才有效。

 

 

 

mysql> explain select * from apn_user where username in ('111aaa', '222aaa');

+----+-------------+----------+------+---------------+------+---------+------+------+-------------+

| id | select_type | table    | type | possible_keys | key  | key_len | ref  | rows | Extra       |

+----+-------------+----------+------+---------------+------+---------+------+------+-------------+

|  1 | SIMPLE      | apn_user | ALL  | username      | NULL | NULL    | NULL |    5 | Using where |

+----+-------------+----------+------+---------------+------+---------+------+------+-------------+

1 row in set (0.00 sec)

从上面的查询优化看,没有用上索引,索引无效。

 

mysql> explain select * from apn_user force index(username) where username in ('111aaa', '222aaa');

+----+-------------+----------+-------+---------------+----------+---------+------+------+-------------+

| id | select_type | table    | type  | possible_keys | key      | key_len | ref  | rows | Extra       |

+----+-------------+----------+-------+---------------+----------+---------+------+------+-------------+

|  1 | SIMPLE      | apn_user | range | username      | username | 194     | NULL |    2 | Using where |

+----+-------------+----------+-------+---------------+----------+---------+------+------+-------------+

1 row in set (0.02 sec)

这里强制使用索引后,就可以发现使用了索引。

 

mysql> explain select * from apn_user where username = '111aaa' or username = '222aaa';

+----+-------------+----------+------+---------------+------+---------+------+------+-------------+

| id | select_type | table    | type | possible_keys | key  | key_len | ref  | rows | Extra       |

+----+-------------+----------+------+---------------+------+---------+------+------+-------------+

|  1 | SIMPLE      | apn_user | ALL  | username      | NULL | NULL    | NULL |    5 | Using where |

+----+-------------+----------+------+---------------+------+---------+------+------+-------------+

1 row in set (0.00 sec)

这个等效于上面的in用法,但这里也没有用到索引。

 

mysql> explain select * from apn_user where id = 1 or name = '111';

+----+-------------+----------+------+---------------+------+---------+------+------+-------------+

| id | select_type | table    | type | possible_keys | key  | key_len | ref  | rows | Extra       |

+----+-------------+----------+------+---------------+------+---------+------+------+-------------+

|  1 | SIMPLE      | apn_user | ALL  | PRIMARY       | NULL | NULL    | NULL |    5 | Using where |

+----+-------------+----------+------+---------------+------+---------+------+------+-------------+

1 row in set (0.00 sec)

这里也没有用到索引。

 

mysql> explain select * from apn_user force index(username) where username = '111aaa' or username = '222aaa';

+----+-------------+----------+-------+---------------+----------+---------+------+------+-------------+

| id | select_type | table    | type  | possible_keys | key      | key_len | ref  | rows | Extra       |

+----+-------------+----------+-------+---------------+----------+---------+------+------+-------------+

|  1 | SIMPLE      | apn_user | range | username      | username | 194     | NULL |    2 | Using where |

+----+-------------+----------+-------+---------------+----------+---------+------+------+-------------+

1 row in set (0.00 sec)

这里强制使用索引后,就可以发现使用了索引。

 

mysql> explain select * from apn_user where username = '111aaa' and username = '222aaa';

+----+-------------+-------+------+---------------+------+---------+------+------+------------------+

| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra            |

+----+-------------+-------+------+---------------+------+---------+------+------+------------------+

|  1 | SIMPLE      | NULL  | NULL | NULL          | NULL | NULL    | NULL | NULL | Impossible WHERE |

+----+-------------+-------+------+---------------+------+---------+------+------+------------------+

1 row in set (0.00 sec)

 

可见在执行查询优化,如果看到“Impossible WHERE”字样,都不是什么好情况!

 

 

 

 

mysql> explain select * from apn_user where day(updated_date) = 20;

+----+-------------+----------+------+---------------+------+---------+------+------+-------------+

| id | select_type | table    | type | possible_keys | key  | key_len | ref  | rows | Extra       |

+----+-------------+----------+------+---------------+------+---------+------+------+-------------+

|  1 | SIMPLE      | apn_user | ALL  | NULL          | NULL | NULL    | NULL |    9 | Using where |

+----+-------------+----------+------+---------------+------+---------+------+------+-------------+

 

1 row in set (0.00 sec)

使用了聚集函数,索引无效

 

 

 

 

 

 

 

 

 

 

exists和in的比较

mysql> select * from apn_user A where username in (select username from apn_user_info B);

+----+---------------------+------------------+------+----------+---------------------+----------+

| id | created_date        | email            | name | password | updated_date        | username |

+----+---------------------+------------------+------+----------+---------------------+----------+

|  1 | 2012-01-20 12:12:12 | 111@gmail.com    | 111  | 111      | 2012-01-20 12:12:12 | 111aaa   |

|  2 | 2012-01-21 12:12:12 | 222@yahoo.com.cn | 222  | 222      | 2012-01-21 12:12:12 | 222aaa   |

|  3 | 2012-02-08 18:01:43 | NULL             | NULL | 333      | NULL                | 333aaa   |

|  4 | 2012-02-08 18:24:39 | NULL             | NULL | 444      | NULL                | 444      |

|  5 | 2012-02-08 18:24:39 | 555@555.com      | 555  | 555      | 2012-02-08 18:24:39 | 555      |

|  6 | NULL                | 666@666.com      | 666  | 666      | NULL                | 666      |

|  7 | NULL                | 777@777.com      | 777  | 777      | NULL                | 777      |

|  8 | NULL                | 888@888.com      | 888  | 888      | NULL                | 888      |

+----+---------------------+------------------+------+----------+---------------------+----------+

8 rows in set (0.00 sec)

 

mysql> explain select * from apn_user A where username in (select username from apn_user_info B);

+----+--------------------+-------+-----------------+---------------+-----------+---------+------+------+--------------------------+

| id | select_type        | table | type            | possible_keys | key       | key_len | ref  | rows | Extra                    |

+----+--------------------+-------+-----------------+---------------+-----------+---------+------+------+--------------------------+

|  1 | PRIMARY            | A     | ALL             | NULL          | NULL      | NULL    | NULL |    9 | Using where              |

|  2 | DEPENDENT SUBQUERY | B     | unique_subquery | NewIndex1     | NewIndex1 | 98      | func |    1 | Using index; Using where |

+----+--------------------+-------+-----------------+---------------+-----------+---------+------+------+--------------------------+

2 rows in set (0.00 sec)

 

mysql> select * from apn_user A where exists (select * from apn_user_info B where B.username = A.username);

+----+---------------------+------------------+------+----------+---------------------+----------+

| id | created_date        | email            | name | password | updated_date        | username |

+----+---------------------+------------------+------+----------+---------------------+----------+

|  1 | 2012-01-20 12:12:12 | 111@gmail.com    | 111  | 111      | 2012-01-20 12:12:12 | 111aaa   |

|  2 | 2012-01-21 12:12:12 | 222@yahoo.com.cn | 222  | 222      | 2012-01-21 12:12:12 | 222aaa   |

|  3 | 2012-02-08 18:01:43 | NULL             | NULL | 333      | NULL                | 333aaa   |

|  4 | 2012-02-08 18:24:39 | NULL             | NULL | 444      | NULL                | 444      |

|  5 | 2012-02-08 18:24:39 | 555@555.com      | 555  | 555      | 2012-02-08 18:24:39 | 555      |

|  6 | NULL                | 666@666.com      | 666  | 666      | NULL                | 666      |

|  7 | NULL                | 777@777.com      | 777  | 777      | NULL                | 777      |

|  8 | NULL                | 888@888.com      | 888  | 888      | NULL                | 888      |

+----+---------------------+------------------+------+----------+---------------------+----------+

8 rows in set (0.00 sec)

 

mysql> explain select * from apn_user A where exists (select * from apn_user_info B where B.username = A.username);

+----+--------------------+-------+--------+---------------+-----------+---------+----------------------+------+--------------------------+

| id | select_type        | table | type   | possible_keys | key       | key_len | ref                  | rows | Extra                    |

+----+--------------------+-------+--------+---------------+-----------+---------+----------------------+------+--------------------------+

|  1 | PRIMARY            | A     | ALL    | NULL          | NULL      | NULL    | NULL                 |    9 | Using where              |

|  2 | DEPENDENT SUBQUERY | B     | eq_ref | NewIndex1     | NewIndex1 | 98      | androidpn.A.username |    1 | Using where; Using index |

+----+--------------------+-------+--------+---------------+-----------+---------+----------------------+------+--------------------------+

 

2 rows in set (0.00 sec)

对于上面的exists和in的两个查询,如果:

1、apn_user的username没建索引,apn_user_info的username也没建索引,exists和in两种情况都无所谓使用索引

2、apn_user的username建了索引,apn_user_info的username也没建索引,exists和in两种情况都不会使用索引

3、apn_user的username没建索引,apn_user_info的username建了索引,exists和in两种情况都会用到索引,使用的是建在apn_user_info的username字段的索引

3、apn_user的username建了索引,apn_user_info的username也建了索引,exists和in两种情况都会用到索引,使用的是建在apn_user_info的username字段的索引

 

查看连接

show processlist;

 

如果需要查看所有连接的话:

show full processlist;

 

 

MySQL C API

 

libmysqlclient

 

 

 

 

 

 

分享到:
评论

相关推荐

    MYSQL

    4.12.1 在 Win32 上安装 MySQL 4.12.2 在 Win95 /Win98上启动 MySQL 4.12.3 在 NT 上启动 MySQL 4.12.4 在 Win32 上运行 MySQL 4.12.5 用 SSH 从 Win32 连接一个远程MySQL 4.12.6 MySQL-Win...

    mysql5.5、mysql5.6、mysql5.7、mysql8 各种版本最新下载合集

    mysql5.5、mysql5.5、mysql5.7、mysql8 各种版本最新下载合集 MySQL是一种关联数据库管理系统,关联数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提 高了灵活性。 MySQL...

    MySql 5.1 参考手册.chm

    1.7.3. MySQL论坛上的MySQL社区支持 1.8. MySQL标准的兼容性 1.8.1. MySQL遵从的标准是什么 1.8.2. 选择SQL模式 1.8.3. 在ANSI模式下运行MySQL 1.8.4. MySQL对标准SQL的扩展 1.8.5. MySQL与标准SQL的差别 1.8.6. ...

    新版 MySQL DBA 高级视频 基于MySQL 5.7 MySQL 8.0版本.rar

    ├─新版MySQL DBA 课件ppt │ 第一课数据库介绍篇.pdf │ 第七课MySQL数据库设计.pdf │ 第三十一课percona-toolkits 的实战及自动化.pdf │ 第三课MySQL授权认证.pdf │ 第九课MySQL字符集.pdf │ 第二十一课MySQL...

    mysql8.0升级版本

    MySQL 8.0 升级版本 在本文中,我们将详细介绍 MySQL 8.0 升级版本的步骤和注意事项。MySQL 是一个流行的开源关系数据库管理系统,广泛应用于各种Web 应用程序中。升级 MySQL 版本可以提高数据库性能、修复 bugs 和...

    C#连接MySQL需要的MySql.Data.dll,MySql.Web.dll

    在C#编程环境中,连接MySQL数据库通常依赖于特定的数据提供者,这就是MySql.Data.dll和MySql.Web.dll的角色。这两个动态链接库(DLL)文件是MySQL官方提供的.NET数据访问组件,使得C#开发者能够轻松地与MySQL服务器...

    mysql57驱动jar包

    mysql57驱动jar包mysql57驱动jar包mysql57驱动jar包mysql57驱动jar包mysql57驱动jar包mysql57驱动jar包mysql57驱动jar包mysql57驱动jar包mysql57驱动jar包mysql57驱动jar包mysql57驱动jar包mysql57驱动jar包mysql57...

    mysql数据库镜像安装包+教程(5.7版本)

    mysql5.7安装教程+mysql5.7镜像安装+mysql学习+mysql5.7镜像包 mysql5.7安装教程+mysql5.7镜像安装+mysql学习+mysql5.7镜像包 mysql5.7安装教程+mysql5.7镜像安装+mysql学习+mysql5.7镜像包 mysql5.7安装教程+mysql...

    Mysql5.6、Mysql5.7 JDBC驱动

    MySQL是世界上最受欢迎的关系型数据库管理系统之一,而JDBC(Java Database Connectivity)是Java语言与数据库交互的标准接口。本文将深入探讨Mysql5.6和Mysql5.7的JDBC驱动,以及如何使用`mysql-connector-java-...

    Windows mysql8.0.36.0详细安装教程,附带MySQL安装包

    在本教程中,我们将深入探讨如何在Windows操作系统上详细安装MySQL 8.0.36.0。MySQL是一个广泛使用的开源关系型数据库管理系统(RDBMS),它在各种规模的企业和项目中扮演着核心角色。MySQL 8.0版本带来了许多性能...

    MySQL ODBC 5.1 Driver(Mysql驱动免安装版)

    MySQL ODBC 5.1 Driver 是一个用于连接MySQL数据库的开放数据库连接(ODBC)驱动程序,它允许用户通过标准的ODBC接口访问MySQL数据库,适用于Windows操作系统。这个版本是免安装的,意味着用户可以直接解压使用,...

    MySQL中文参考手册.chm

    MySQL中文参考手册.chm 449kb &lt;br/&gt;0 译者序 1 MySQL的一般的信息 1.1 什么是MySQL? 1.2 关于本手册 1.2.1 本手册中使用的约定 1.3 MySQL的历史 1.4 MySQL的主要特征 1.5...

    mysql5.1中文手册

    MySQL论坛上的MySQL社区支持 1.8. MySQL标准的兼容性 1.8.1. MySQL遵从的标准是什么 1.8.2. 选择SQL模式 1.8.3. 在ANSI模式下运行MySQL 1.8.4. MySQL对标准SQL的扩展 1.8.5. MySQL与标准SQL的...

    mysql 5.7 中文文档

    MySQL 5.7中文文档是针对这个特定数据库版本的详细技术参考,包含了丰富的信息,适合开发者、管理员和学习者使用。文档的翻译质量被描述为“还行”,尽管资源可能不易找到,但提供了全面的指南。 该文档涵盖了从...

    mysql驱动jar 文件适用MySQL5.7

    MySQL驱动jar文件是Java应用程序与MySQL数据库之间通信的关键组件,主要功能是提供Java Database Connectivity (JDBC) API,使得Java开发者能够通过编写Java代码来执行SQL语句,从而操作MySQL数据库。标题提到的...

    mysql 5.5版 头文件(mysql.h等)

    例如,`mysql_init()`用于初始化一个MySQL连接结构,`mysql_real_connect()`用于建立实际的数据库连接,`mysql_query()`用于执行SQL查询,而`mysql_store_result()`和`mysql_use_result()`则用于处理查询结果。...

    mysql8、mysql5两个版本驱动

    MySQL是世界上最受欢迎的关系型数据库管理系统之一,其驱动程序是Java应用程序连接MySQL数据库的关键组件。本文将详细介绍MySQL 8和MySQL 5驱动的区别以及与JDK版本的兼容性问题。 首先,MySQL 8和5的主要区别在于...

    涂抹MySQL 跟着三思一步一步学MySQL

    《涂抹MySQL:跟着三思一步一步学MySQL》是一本旨在帮助初学者和中级用户深入理解MySQL数据库系统的教程。这本书通过清晰的解释和实例,逐步引导读者掌握MySQL的核心概念和技术。MySQL是一种广泛使用的开源关系型...

    Mysql转Oracle软件 DBMover for Mysql to Oracle

    Dbmover for Mysql to Oracle 是高效的将Mysql导入到Oracle数据库的工具。 使用DBMover可以灵活定义Mysql和Oracle之间表和字段的对照关系,也可以在DBMover创建一个查询,把查询结果当作源表转入到Oracle中。 ...

Global site tag (gtag.js) - Google Analytics