List Logged In Unix Users
List Logged In Unix Users
Unix has many commands to list users who are logged in.
These commands include `w`, `who`, and `users`:
Unix has many commands to list users who are logged in.
These commands include `w`, `who`, and `users`:
To list all users on a Unix system, even the ones who are not logged in, look at the /etc/password file.
$ cat /etc/passwd
...
george:*:1009:1009:George Washington:/home/george:/usr/bin/bash
tom:*:1016:1016:Thomas Jefferson:/home/tom:/usr/bin/bash
al:*:1017:1017:Alexander Hamilton:/home/alex:/usr/bin/bash
...
You can use the `cut` command to only see one field from the password file.
For example, to just see the Unix user names, use the command “$ cat /etc/passwd | cut -d: -f1″.
$ cat /etc/passwd | cut -d: -f1
...
george
tom
al
...
Or, to only see the GECOS field (i.e. the account holders real name), try this:
$ cat /etc/passwd | cut -d: -f5
...
George Washinton
Thomas Jefferson
Alexander Hamilton
...
Note that you will also see Unix system accounts, such as “root
Name |
Manual Page |
Description |
| alias | csh(1) | Create an alias for a command sequence, see csh(1) |
| apropos | apropos(1) | locate commands by keyword lookup |
| banner | banner(1V) | display a string in large letters |
| bc | bc(1) | arbitrary-precision arithmetic language |
| bg | csh(1) | Run a suspended job in the background, see csh(1) |
| cal | cal(1) | display a calendar |
| cancel | lp(1) | send/cancel requests to a printer |
| cat | cat(1V) | concatenate and display |
| cc | cc(1V) | C compiler |
| cd | cd(1) | change working directory |
| chgrp | chgrp(1) | change the group ownership of a file |
| chmod | chmod(1V) | change the permissions mode of a file |
| chsh | passwd(1) | change local or NIS password information |
| clear | clear(1) | clear the terminal screen |
| compress | compress(1) | compress or expand files |
| cp | cp(1) | copy files |
| crontab | crontab(1) | install, edit, remove or list a user’s crontab file |
| csh | csh(1) | shell with a C-like syntax and advanced interactive features |
| date | date(1V) | display or set the date |
| dbx | dbx(1) | source-level debugger |
| df | df(1V) | report free disk space on file systems |
| diff | diff(1) | display line-by-line differences between pairs of text files |
| dircmp | dircmp(1V) | compare directories |
| dirs | csh(1) | Display the directory stack, see csh(1) |
| dos2unix | dos2unix(1) | convert text file from DOS format to ISO format |
| du | du(1V) | display the number of disk blocks used per directory or file |
| echo | echo(1V) | echo arguments to the standard output |
| egrep | grep(1V) | search a file for a string or regular expression |
| eject | eject(1) | eject media device from drive |
| exec | csh(1) | Execute a command in place of the current shell, see csh(1) |
| exit | csh(1) | Exit the current shell, see csh(1) |
| fdformat | fdformat(1) | format diskettes |
| fg | csh(1) | Resume executing a suspended job in the foreground, see csh(1) |
| fgrep | grep(1V) | search a file for a string or regular expression |
| file | file(1) | determine the type of a file by examining its contents |
| find | find(1) | find files by name, or by other characteristics |
| finger | finger(1) | display information about users |
| from | from(1) | display the sender and date of newly-arrived mail messages |
| ftp | ftp(1C) | file transfer program |
| grep | grep(1V) | search a file for a string or regular expression |
| groups | groups(1) | display a user’s group memberships |
| head | head(1) | display first few lines of specified files |
| history | csh(1) | Display recently typed commands, see csh(1) |
| hostid | hostid(1) | print the numeric identifier of the current host |
| hostname | hostname(1) | set or print name of current host system |
| id | id(1V) | print the user name and ID, and group name and ID |
| jobs | csh(1) | List jobs suspended or backgrounded from this shell, see csh(1) |
| kill | kill(1) | send a signal to a process, or terminate a process |
| last | last(1) | indicate last logins by user or terminal |
| limit | csh(1) | Set or display resource limits, see csh(1) |
| line | line(1) | read one line |
| lint | lint(1V) | a C program verifier |
| ln | ln(1V) | make hard or symbolic links to files |
| login | login(1) | log in to the system |
| logname | logname(1) | get the name by which you logged in |
| logout | csh(1) | Terminate a login shell, see csh(1) |
| lp | lp(1) | send/cancel requests to a printer |
| lpq | lpq(1) | display the queue of printer jobs |
| lpr | lpr(1) | send a job to the printer |
| lprm | lprm(1) | remove jobs from the printer queue |
| lpstat | lpstat(1) | display the printer status information |
| ls | ls(1V) | list the contents of a directory |
| mach | mach(1) | display the processor type of the current host |
| man | man(1) | display reference manual pages |
| mesg | mesg(1) | permit or deny messages on the terminal |
| mkdir | mkdir(1) | make a directory |
| more | more(1) | browse or page through a text file |
| mv | mv(1) | move or rename files |
| newgrp | newgrp(1) | log in to a new group |
| nice | nice(1) | run a command at low priority |
| passwd | passwd(1) | change local or password information |
| popd | csh(1) | Pop the directory stack, see csh(1) |
| printenv | printenv(1) | display environment variables currently set |
| ps | ps(1) | display the status of current processes |
| pushd | csh(1) | Push a directory onto the directory stack, see csh(1) |
| pwd | pwd(1) | display the pathname of the current working directory |
| quota | quota(1) | display a user’s disk quota and usage |
| rehash | csh(1) | Rescan the execution path, see csh(1) |
| reset | tset(1) | establish or restore terminal characteristics |
| rlogin | rlogin(1C) | remote login |
| rm | rm(1) | remove (unlink) files or directories |
| rmdir | rm(1) | remove (unlink) files or directories |
| rsh | rsh(1C) | remote shell |
| rup | rup(1C) | show host status of local machines (RPC version) |
| ruptime | ruptime(1C) | show host status of local machines |
| rusers | rusers(1C) | who’s logged in on local machines (RPC version) |
| rwall | rwall(1C) | write to all users over a network |
| rwho | rwho(1C) | who’s logged in on local machines |
| script | script(1) | make typescript of a terminal session |
| setenv | csh(1) | Set or display environment variables, see csh(1) |
| set | csh(1) | Set or display shell variables, see csh(1) |
| sh | sh(1) | standard UNIX system shell and command-level language |
| sleep | sleep(1) | suspend execution for a specified interval |
| sort | sort(1V) | sort and collate lines |
| source | csh(1) | Read commands from a file, see csh(1) |
| spell | spell(1) | report spelling errors |
| spellin | spell(1) | report spelling errors |
| strings | strings(1) | find printable strings in an object file or binary |
| strip | strip(1) | remove symbols and relocation bits from an object file |
| stty | stty(1V) | set or alter the options for a terminal |
| su | su(1V) | super-user, temporarily switch to a new user ID |
| suspend | csh(1) | Suspend the shell, see csh(1) |
| sync | sync(1) | update the super block; force changed blocks to the disk |
| tail | tail(1) | display the last part of a file |
| talk | talk(1) | talk to another user |
| tar | tar(1) | create tape archives, and add or extract files |
| telnet | telnet(1C) | user interface to a remote system using the TELNET protocol |
| time | time(1V) | time a command |
| touch | touch(1V) | update the access and modification times of a file |
| trace | trace(1) | trace system calls and signals |
| tset | tset(1) | establish or restore terminal characteristics |
| tty | tty(1) | display the name of the terminal |
| umask | csh(1) | Set or display the file permissions mask, see csh(1) |
| unalias | csh(1) | Discard an alias, see csh(1) |
| uncompress | compress(1) | compress or expand files, display expanded contents |
| unix2dos | unix2dos(1) | convert text file from ISO format to DOS format |
| unlimit | csh(1) | Remove a limit on a resource, see csh(1) |
| unset | csh(1) | Discard a shell variable, see csh(1) |
| unsetenv | csh(1) | Discard an envrionment variable, see csh(1) |
| uptime | uptime(1) | show how long the system has been up |
| users | users(1) | display a compact list of users logged in |
| uudecode | uuencode(1C) | encode a binary file, or decode its ASCII representation |
| uuencode | uuencode(1C) | encode a binary file, or decode its ASCII representation |
| vacation | vacation(1) | reply to mail automatically |
| w | w(1) | who is logged in, and what are they doing |
| wall | wall(1) | write to all users logged in |
| wc | wc(1) | display a count of lines, words and characters |
| whatis | whatis(1) | display a one-line summary about a keyword |
| whereis | whereis(1) | locate the binary, source, and manual page for a command |
| which | which(1) | locate a command; display its pathname or alias |
| who | who(1) | who is logged in on the system |
| whoami | whoami(1) | display the effective current username |
| whois | whois(1) | Internet user name directory service |
| write | write(1) | write a message to another user |
2、在shell中使用find结合grep进行文件的替换
# find ./ -exec grep str1 ‘{}’ \; -exec sed -i.bak s/str1/str2/g ‘{}’ \;
上面命令可以在当前目录下(包括子目录)查找包含str1的文件,自动替换成str2,并且生成源文件的bak文件
更多方法正在不断收集更新中。。。
ps -wwaux
kill -HUP pid (restart on process)
kill -9 pid
1 HUP (hang up)
2 INT (interrupt)
3 QUIT (quit)
6 ABRT (abort)
9 KILL (non-catchable, non-ignorable kill)
14 ALRM (alarm clock)
15 TERM (software termination signal)
来源:ZOL.COM.CN | 2008年05月28日 | 作者:
启动Mysql时加参数–log-slow-queries来记录执行时间超过long_query_time秒的sql:
/usr/sbin/mysqld –basedir=/usr –datadir=/var/lib/mysql–user=mysql –pid-file=/var/run/mysqld/mysqld.pid–skip-locking –port=3306 –socket=/var/run/mysqld/mysqld.sock –log-slow-queries=/var/log/mysql/slow.log
explain来了解SQL执行的状态。
explain select * from wp_postsG;
使用show status like “Handler_read%”; 来了解索引的效果。
Handler_read_key 值高表示索引效果好,Handler_read_rnd_next值高表示索引低效。
用show processlist 查看当前运行状态。
mysql> show processlist;
+—–+————-+——————–+
| Id | User | Host | db | Command | Time| State | Info
+—–+————-+——————–+
|207|root |192.168.0.20:51718 |mytest | Sleep | 5 | | NULL
|208|root |192.168.0.20:51719 |mytest | Sleep | 5 | | NULL
|220|root |192.168.0.20:51731 |mytest |Query | 84 | Locked |
select bookname,culture,value,type from book where id=001
先简单说一下各列的含义和用途,第一列,id,不用说了吧,一个标识,你要kill一个语句的时候很有用。user列,显示单前用户,如果不是root,这个命令就只显示你权限范围内的sql语句。host列,显示这个语句是从哪个ip的哪个端口上发出的。呵呵,可以用来追踪出问题语句的用户。db列,显示这个进程目前连接的是哪个数据库。command列,显示当前连接的执行的命令,一般就是休眠(sleep),查询(query),连接(connect)。time列,此这个状态持续的时间,单位是秒。state列,显示使用当前连接的sql语句的状态,很重要的列,后续会有所有的状态的描述,请注意,state只是语句执行中的某一个状态,一个sql语句,已查询为例,可能需要经过copying to tmp table,Sorting result,Sending data等状态才可以完成,info列,显示这个sql语句,因为长度有限,所以长的sql语句就显示不全,但是一个判断问题语句的重要依据。
这个命令中最关键的就是state列,mysql列出的状态主要有以下几种:
Checking table
正在检查数据表(这是自动的)。
Closing tables
正在将表中修改的数据刷新到磁盘中,同时正在关闭已经用完的表。这是一个很快的操作,如果不是这样的话,就应该确认磁盘空间是否已经满了或者磁盘是否正处于重负中。
Connect Out
复制从服务器正在连接主服务器。
Copying to tmp table on disk
由于临时结果集大于 tmp_table_size,正在将临时表从内存存储转为磁盘存储以此节省内存。
Creating tmp table
正在创建临时表以存放部分查询结果。
deleting from main table
服务器正在执行多表删除中的第一部分,刚删除第一个表。
deleting from reference tables
服务器正在执行多表删除中的第二部分,正在删除其他表的记录。
Flushing tables
正在执行 FLUSH TABLES,等待其他线程关闭数据表。
Killed
发送了一个kill请求给某线程,那么这个线程将会检查kill标志位,同时会放弃下一个kill请求。MySQL会在每次的主循环中检查kill标志位,不过有些情况下该线程可能会过一小段才能死掉。如果该线程程被其他线程锁住了,那么kill请求会在锁释放时马上生效。
Locked
被其他查询锁住了。
Sending data
正在处理 SELECT 查询的记录,同时正在把结果发送给客户端。
Sorting for group
正在为 group BY 做排序。
Sorting for order
正在为 ORDER BY 做排序。
Opening tables
这个过程应该会很快,除非受到其他因素的干扰。例如,在执 ALTER TABLE 或 LOCK TABLE 语句行完以前,数据表无法被其他线程打开。 正尝试打开一个表。
Removing duplicates
正在执行一个 SELECT DISTINCT 方式的查询,但是MySQL无法在前一个阶段优化掉那些重复的记录。因此,MySQL需要再次去掉重复的记录,然后再把结果发送给客户端。
Reopen table
获得了对一个表的锁,但是必须在表结构修改之后才能获得这个锁。已经释放锁,关闭数据表,正尝试重新打开数据表。
Repair by sorting
修复指令正在排序以创建索引。
Repair with keycache
修复指令正在利用索引缓存一个一个地创建新索引。它会比 Repair by sorting 慢些。
Searching rows for uPDAte
正在讲符合条件的记录找出来以备更新。它必须在 UPDATE 要修改相关的记录之前就完成了。
Sleeping
正在等待客户端发送新请求.
System lock
正在等待取得一个外部的系统锁。如果当前没有运行多个 mysqld 服务器同时请求同一个表,那么可以通过增加 –skip-external-locking参数来禁止外部系统锁。
Upgrading lock
INSERT DELAYED 正在尝试取得一个锁表以插入新记录。
UPDAting
正在搜索匹配的记录,并且修改它们。
User Lock
正在等待 GET_LOCK()。
Waiting for tables
该线程得到通知,数据表结构已经被修改了,需要重新打开数据表以取得新的结构。然后,为了能的重新打开数据表,必须等到所有其他线程关闭这个表。以下几种情况下会产生这个通知:FLUSH TABLES tbl_name, ALTER TABLE, RENAME TABLE, REPAIR TABLE, ANALYZE TABLE, 或 OPTIMIZE TABLE。
waiting for handler insert
INSERT DELAYED 已经处理完了所有待处理的插入操作,正在等待新的请求。
大部分状态对应很快的操作,只要有一个线程保持同一个状态好几秒钟,那么可能是有问题发生了,需要检查一下。
还有其它的状态没在上面中列出来,不过它们大部分只是在查看服务器是否有存在错误是才用得着。
标签:mysql数据库_mysql 创建数据库_mysql 删除数据库_mysql 数据库备份_mysql数据库下载_mysql 导出数据库_免费mysql数据库_php连接mysql数据库_mysql 建立数据库_mysql 导入数据库
当你提交一个查询的时候,MySQL会分析它,看是否可以做一些优化使处理该查询的速度更快。这一部分将介绍查询优化器是如何工作的。如果你想知道MySQL采用的优化手段梢圆榭碝ySQL参考手册。
当然,MySQL查询优化器也利用了索引,但是它也使用了其它一些信息。例如,如果你提交如下所示的查询,那么无论数据表有多大,MySQL执行它的速度都会非常快:
| SELECT * FROM tbl_name WHERE 0; |
在这个例子中,MySQL查看WHERE子句,认识到没有符合查询条件的数据行,因此根本就不考虑搜索数据表。你可以通过提供一个EXPLAIN语句看到这种情况,这个语句让MySQL显示自己执行的但实际上没有真正地执行的SELECT查询的一些信息。如果要使用EXPLAIN,只需要在EXPLAIN单词放在SELECT语句的前面:
| mysql> EXPLAIN SELECT * FROM tbl_name WHERE 0\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: NULL type: NULL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: NULL Extra: Impossible WHERE |
通常情况下,EXPLAIN返回的信息比上面的信息要多一些,还包括用于扫描数据表的索引、使用的联结类型、每张数据表中估计需要检查的数据行数量等非空(NULL)信息。
优化器是如何工作的
MySQL查询优化器有几个目标,但是其中最主要的目标是尽可能地使用索引,并且使用最严格的索引来消除尽可能多的数据行。你的最终目标是提交SELECT语句查找数据行,而不是排除数据行。优化器试图排除数据行的原因在于它排除数据行的速度越快,那么找到与条件匹配的数据行也就越快。如果能够首先进行最严格的测试,查询就可以执行地更快。假设你的查询检验了两个数据列,每个列上都有索引:
| SELECT col3 FROM mytable WHERE col1 = ’some value’ AND col2 = ’some other value’; |
假设col1上的测试匹配了900个数据行,col2上的测试匹配了300个数据行,而同时进行的测试只得到了30个数据行。先测试Col1会有900个数据行,需要检查它们找到其中的30个与col2中的值匹配记录,其中就有870次是失败了。先测试col2会有300个数据行,需要检查它们找到其中的30个与col1中的值匹配的记录,只有270次是失败的,因此需要的计算和磁盘I/O更少。其结果是,优化器会先测试col2,因为这样做开销更小。
你可以通过下面一个指导帮助优化器更好地利用索引:
尽量比较数据类型相同的数据列。当你在比较操作中使用索引数据列的时候,请使用数据类型相同的列。相同的数据类型比不同类型的性能要高一些。例如,INT与BIGINT是不同的。CHAR(10)被认为是CHAR(10)或VARCHAR(10),但是与CHAR(12)或VARCHAR(12)不同。如果你所比较的数据列的类型不同,那么可以使用ALTER TABLE来修改其中一个,使它们的类型相匹配。
尽可能地让索引列在比较表达式中独立。如果你在函数调用或者更复杂的算术表达式条件中使用了某个数据列,MySQL就不会使用索引,因为它必须计算出每个数据行的表达式值。有时候这种情况无法避免,但是很多情况下你可以重新编写一个查询让索引列独立地出现。
下面的WHERE子句显示了这种情况。它们的功能相同,但是对于优化目标来说就有很大差异了:
| WHERE mycol < 4 / 2 WHERE mycol * 2 < 4 |
对于第一行,优化器把表达式4/2简化为2,接着使用mycol上的索引来快速地查找小于2的值。对于第二个表达式,MySQL必须检索出每个数据行的mycol值,乘以2,接着把结果与4进行比较。在这种情况下,不会使用索引。数据列中的每个值都必须被检索到,这样才能计算出比较表达式左边的值。
我们看另外一个例子。假设你对date_col列进行了索引。如果你提交一条如下所示的查询,就不会使用这个索引:
| SELECT * FROM mytbl WHERE YEAR(date_col) < 1990; |
这个表达式不会把1990与索引列进行比较;它会把1990与该数据列计算出来的值比较,而每个数据行都必须计算出这个值。其结果是,没有使用date_col上的索引,因为执行这样的查询需要全表扫描。怎么解决这个问题呢?只需要使用文本日期,接着就可以使用date_col上的索引来查找列中匹配的值了:
| WHERE date_col < ’1990-01-01’ |
但是,假设你没有特定的日期。你可能希望找到一些与今天相隔固定的几天的日期的记录。表达这种类型的比较有很多种方法–它们的效率并不同。下面就有三种:
| WHERE TO_DAYS(date_col) - TO_DAYS(CURDATE()) < cutoff WHERE TO_DAYS(date_col) < cutoff + TO_DAYS(CURDATE()) WHERE date_col < DATE_ADD(CURDATE(), INTERVAL cutoff DAY) |
对于第一行,不会用到索引,因为每个数据行都必须检索以计算出TO_DAYS(date_col)的值。第二行要好一些。Cutoff和TO_DAYS(CURDATE())都是常量,因此在处理查询之前,比较表达式的右边可以被优化器一次性计算出来,而不需要每个数据行都计算一次。但是date_col列仍然出现在函数调用中,它阻止了索引的使用。第三行是这几个中最好的。同样,在执行查询之前,比较表达式的右边可以作为常量一次性计算出来,但是现在它的值是一个日期。这个值可以直接与date_col值进行比较,再也不需要转换成天数了。在这种情况下,会使用索引。
在LIKE模式的开头不要使用通配符。有些字符串搜索使用如下所示的WHERE子句:
| WHERE col_name LIKE ’%string%’ |
如果你希望找到那些出现在数据列的任何位置的字符串,这个语句就是对的。但是不要因为习惯而简单地把”%”放在字符串的两边。如果你在查找出现在数据列开头的字符串,就删掉前面的”%”。假设你要查找那些类似MacGregor或MacDougall等以”Mac”开头的名字。在这种情况下,WHERE子句如下所示:
| WHERE last_name LIKE ’Mac%’ |
优化器查看该模式中词首的文本,并使用索引找到那些与下面的表达式匹配的数据行。下面的表达式是使用last_name索引的另一种形式:
| WHERE last_name >= ’Mac’ AND last_name < ’Mad’ |
这种优化不能应用于使用了REGEXP操作符的模式匹配。REGEXP表达式永远不会被优化。
帮助优化器更好的判断索引的效率。在默认情况下,当你把索引列的值与常量进行比较的时候,优化器会假设键值在索引内部是均匀分布的。在决定进行常量比较是否褂盟饕氖焙颍呕骰峥焖俚丶觳樗饕兰瞥龌嵊玫蕉嗌俑鍪堤澹╡ntry)。对应MyISAM、InnoDB和BDB数据表来说,你可以使用ANALYZE TABLE让服务器执行对键值的分析。它会为优化器提供更好的信息。
使用EXPLAIN验证优化器的操作。EXPLAIN语句可以告诉你是否使用了索引。当你试图用另外的方式编写语句或检查添加索引是否会提高查询执行效率的时候,这些信息对你是有帮助的。
在必要的时候给优化器一些提示。正常情况下,MySQL优化器自由地决定扫描数据表的次序来最快地检索数据行。在有些场合中优化器没有作出最佳选择。如果你察觉这种现象发生了,就可以使用STRAIGHT_JOIN关键字来重载优化器的选择。带有STRAIGHT_JOIN的联结类似于交叉联结,但是强迫数据表按照FROM子句中指定的次序来联结。
在SELECT语句中有两个地方可以指定STRAIGHT_JOIN。你可以在SELECT关键字和选择列表之间的位置指定,这样会对语句中所有的交叉联结产生影响;你也可以在FROM子句中指定。下面的两个语句功能相同:
| SELECT STRAIGHT_JOIN … FROM t1, t2, t3 … ; SELECT … FROM t1 STRAIGHT_JOIN t2 STRAIGHT_JOIN t3 … ; |
分别在带有STRAIGHT_JOIN和不带STRAIGHT_JOIN的情况下运行这个查询;MySQL可能因为什么原因没有按照你认为最好的次序使用索引(你可以使用EXPLAIN来检查MySQL处理每个语句的执行计划)。
你还可以使用FORCE INDEX、USE INDEX或IGNORE INDEX来指导服务器如何使用索引。
利用优化器更加完善的区域。MySQL可以执行联结和子查询,但是子查询是最近才支持的,是在MySQL 4.1中添加的。因而在很多情况下,优化器对联结操作的调整比对子查询的调整要好一些。当你的子查询执行地很慢的时候,这就是一条实际的提示。有一些子查询可以使用逻辑上相等的联结来重新表达。在可行的情况下,你可以把子查询重新改写为联结,看是否执行地快一些。
测试查询的备用形式,多次运行。当你测试查询的备用形式的时候(例如,子查询与等同的联结操作对比),每种方式都应该多次运行。如果两种形式都只运行了一次,那么你通常会发现第二个查询比第一个快,这是因为第一个查询得到的信息仍然保留在缓存中,以至于第二个查询没有真正地从磁盘上读取数据。你还应该在系统负载相对平稳的时候运行查询,以避免系统中其它的事务影响结果。
避免过度地使用MySQL自动类型转换。MySQL会执行自动的类型转换,但是如果你能够避免这种转换操作,你得到的性能就更好了。例如,如果num_col是整型数据列,那么下面这些查询将返回相同的结果:
| SELECT * FROM mytbl WHERE num_col = 4; SELECT * FROM mytbl WHERE num_col = ’4’; |
但是第二个查询涉及到了类型转换。转换操作本身为了把整型和字符串型转换为双精度型进行比较,使性能恶化了。更严重的情况是,如果num_col是索引的,那么涉及到类型转换的比较操作不会使用索引。
相反类型的比较操作(把字符串列与数值比较)也会阻止索引的使用。假设你编写了如下所示的查询:
| SELECT * FROM mytbl WHERE str_col = 4; |
在这个例子中,不会使用str_col上的索引,因为在把str_col中的字符串值转换成数值的时候,可能有很多值等于4(例如’4’、’4.0’和’4th’)。分辨哪些值符合要求的唯一办法是读取每个数据行并执行比较操作。
使用EXPLAIN来检查优化器的操作
EXPLAIN对于了解优化器生成的、用于处理语句的执行计划的内部信息是很有帮助的。在这一部分中,我们将解释EXPLAIN的两种用途:
· 查看采用不同的方式编写的查询是否影响了索引的使用。
· 查看向数据表添加索引对优化器生成高效率执行计划的能力的影响。
这一部分只讨论与示例相关的EXPLAIN输入字段。
前面,在”优化器是如何工作的”部分中我们得出的观点是,你编写表达式的方式将决定优化器是否能使用可用的索引。特别是上面的讨论使用了下面三个逻辑相等的WHERE子句的例子,只有第三个允许使用索引:
| WHERE TO_DAYS(date_col) - TO_DAYS(CURDATE()) < cutoff WHERE TO_DAYS(date_col) < cutoff + TO_DAYS(CURDATE()) WHERE date_col < DATE_ADD(CURDATE(), INTERVAL cutoff DAY) |
EXPLAIN允许你查看编写表达式的某种方式是否比另外的方式好一些。为了看到结果,让我们分别用这三个WHERE子句搜索成员表中过期的数据列值,把cutoff值设为30天。为了看到索引的使用和表达式编写方式之间的关系,我们首先对expiration列进行索引:
| mysql> ALTER TABLE member ADD INDEX (expiration); |
接着在每个表达式形式上使用EXPLAIN,看优化器生成了什么样的执行计划:
| mysql> EXPLAIN SELECT * FROM MEMBER -> WHERE TO_DAYS(expiration) - TO_DAYS(CURDATE()) < 30\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: MEMBER type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 102 Extra: Using where mysql> EXPLAIN SELECT * FROM MEMBER -> WHERE TO_DAYS(expiration) < 30 + TO_DAYS(CURDATE())\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: MEMBER type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 102 Extra: Using where mysql> EXPLAIN SELECT * FROM MEMBER -> WHERE expiration < DATE_ADD(CURDATE(), INTERVAL 30 DAY)\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: MEMBER type: range possible_keys: expiration key: expiration key_len: 4 ref: NULL rows: 6 Extra: Using where |
上面的结果显示,前面两个语句没有使用索引。类型(type)值表明了将如何从数据表中读取信息。ALL意味着”将检查所有的记录”。也就是说,它会执行全表扫描,没有利用索引。每个与键相关的列都是NULL也表明没有使用索引。
与此形成对比的是,第三个语句的结果显示,采用这种方式编写的WHERE子句,优化器可以使用expiration列上的索引:
· 类型(type)值表明它可以使用索引来搜索特定范围的值(小于右边表达式给定的值)。
· 可能键(possible_keys)和键(key)值显示expiration上的索引已经被考虑作为备选索引,并且它也是真正使用的索引。
· 行数(rows)值显示优化器估计自己需要检查6个数据行来处理该查询。这比前面两个执行计划的102小很多。
EXPLAIN的第二种用途是查看添加索引是否能帮助优化器更高效率地执行语句。我将使用两个未被索引的数据表。它足够显示建立索引的效率。相同的规则可以应用于涉及多表的更加复杂的联结操作。
假设我们有两个数据表t1和t2,每个有1000行,包含的值从1到1000。下面的查询查找出两个表中值相同的数据行:
| mysql> SELECT t1.i1, t2.i2 FROM t1, t2 WHERE t1.i1 = t2.i2; +——+——+ | i1 | i2 | +——+——+ | 1 | 1 | | 2 | 2 | | 3 | 3 | | 4 | 4 | | 5 | 5 | … |
两个表都没有索引的时候,EXPLAIN产生下面的结果:
| mysql> EXPLAIN SELECT t1.i1, t2.i2 FROM t1, t2 WHERE t1.i1 = t2.i2\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: t1 type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 1000 Extra: *************************** 2. row *************************** id: 1 select_type: SIMPLE table: t2 type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 1000 Extra: Using where |
类型列中的ALL表明要进行检查所有数据行的全表扫描。可能键列中的NULL表明没有找到用于提高查询速度的备选索引(键、键长度和参考列都是NULL也是因为缺少合适的索引)。Using where表明使用WHERE子句中的信息来识别合格的数据行。
这段信息告诉我们,优化器没有为提高执行查询的效率找到任何有用的信息:
· 它将对t1表进行全表扫描。
· 对于t1中的每一行,它将执行t2的全表扫描,使用WHERE子句中的信息识别出合格的行。
行数值显示了优化器估计的每个阶段查询需要检查的行数。T1的估计值是1000,因为1000可以完成全表扫描。相似地,t2的估计值也是1000,但是这个值是对于t1的每一行的。换句话说,优化器所估计的处理该查询所需要检查的数据行组合的数量是1000×1000,也就是一百万。这会造成很大的浪费,因为实际上只有1000个组合符合WHERE子句的条件。
为了使这个查询的效率更高,给其中一个联结列添加索引并重新执行EXPLAIN语句:
| mysql> ALTER TABLE t2 ADD INDEX (i2); mysql> EXPLAIN SELECT t1.i1, t2.i2 FROM t1, t2 WHERE t1.i1 = t2.i2\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: t1 type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 1000 Extra: *************************** 2. row *************************** id: 1 select_type: SIMPLE table: t2 type: ref possible_keys: i2 key: i2 key_len: 5 ref: sampdb.t1.i1 rows: 10 Extra: Using where; Using index |
我们可以看到性能提高了。T1的输出没有改变(表明还是需要进行全表扫描),但是优化器处理t2的方式就有所不同了:
· 类型从ALL改变为ref,意味着可以使用参考值(来自t1的值)来执行索引查找,定位t2中合格的数据行。
· 参考值在参考(ref)字段中给出了:sampdb.t1.i1。
· 行数值从1000降低到了10,显示出优化器相信对于t1中的每一行,它只需要检查t2中的10行(这是一个悲观的估计值。实际上,在t2中只有一行与t1中数据行匹配。我们在后面会看到如何帮助优化器改善这个估计值)。数据行组合的全部估计值使1000×10=10000。它比前面的没有索引的时候估计出来的一百万好多了。
对t1进行索引有价值吗?实际上,对于这个特定的联结操作,扫描一张表是必要的,因此没有必要对t1建立索引。如果你想看到效果,可以索引t1.i1并再次运行EXPLAIN:
| mysql> ALTER TABLE t1 ADD INDEX (i1); mysql> EXPLAIN SELECT t1.i1, t2.i2 FROM t1, t2 WHERE t1.i1 = t2.i2\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: t1 type: index possible_keys: i1 key: i1 key_len: 5 ref: NULL rows: 1000 Extra: Using index *************************** 2. row *************************** id: 1 select_type: SIMPLE table: t2 type: ref possible_keys: i2 key: i2 key_len: 5 ref: sampdb.t1.i1 rows: 10 Extra: Using where; Using index |
上面的输出与前面的EXPLAIN的输出相似,但是添加索引对t1的输出有一些改变。类型从NULL改成了index,附加(Extra)从空的改成了Using index。这些改变表明,尽管对索引的值仍然需要执行全表扫描,但是优化器还是可以直接从索引文件中读取值,根据不需要使用数据文件。你可以从MyISAM表中看到这类结果,在这种情况下,优化器知道自己只询问索引文件就能够得到所有需要的信息。对于InnoDB 和BDB表也有这样的结果,在这种情况下优化器可以单独使用索引中的信息而不用搜索数据行。
我们可以运行ANALYZE TABLE使优化器进一步优化估计值。这会引起服务器生成键值的静态分布。分析上面的表并再次运行EXPLAIN得到了更好的估计值:
| mysql> ANALYZE TABLE t1, t2; mysql> EXPLAIN SELECT t1.i1, t2.i2 FROM t1, t2 WHERE t1.i1 = t2.i2\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: t1 type: index possible_keys: i1 key: i1 key_len: 5 ref: NULL rows: 1000 Extra: Using index *************************** 2. row *************************** id: 1 select_type: SIMPLE table: t2 type: ref possible_keys: i2 key: i2 key_len: 5 ref: sampdb.t1.i1 rows: 1 Extra: Using where; Using index |
在这种情况下,优化器估计在t2中与t1的每个值匹配的数据行只有一个。
重载优化过程 这个过程听起来多余,但是有时候你还是希望去掉某些MySQL优化行为的:
重载优化器的表联结次序。使用STRAIGHT_JOIN强迫优化器按照特定的次序使用数据表。在这样操作的时候,你必须对数据表进行排序,这样才能保证第一张表是被选择的行数最少的表。如果你不能确定被选择行数最少的是哪一张表,那么就把行数最多的放到第一的位置。换句话说,试着对表进行排序,使最有约束力的选择出现在最前面。你对可能的备选数据行缩小地越早,执行查询的性能就越好。请确保在带有STRAIGHT_JOIN和不带STRAIGHT_JOIN的时候分别执行该查询。有时候由于某些原因的存在,优化器没有按照你认定的方式联结数据表,STRAIGHT_JOIN也可能没有实际的帮助作用。
另一个可能性是在联结的数据表列表中的某个表的后面使用FORCE INDEX、USE INDEX和IGNORE INDEX调节符来告诉MySQL如何使用索引。这在优化器没有做出正确选择的时候是有用处的。
以最小的代价清空一张表。当需要完全地清空一张MyISAM数据表的时候,最快的方法是删除它并利用它的.frm文件中存储的脚本来重新建立它。使用TRUNCATE TABLE语句实现:
| TRUNCATE TABLE tbl_name; |
通过重新建立MyISAM数据表来清空它的这种服务器优化措施使该操作非常快,因为不需要单独地逐行删除。
但是TRUNCATE TABLE也带来了一些副作用,在某些环境中是不符合要求的:
· TRUNCATE TABLE不一定能够计算出被删除的数据列的精确数量。如果你需要这个数值,请使用不带WHERE子句的DELETE语句:
| DELETE FROM tbl_name; |
· 但是,通过重新建立来清空数据表,它可能会把序号的起始值设置为1。为了避免这种情况,请使用”不优化的”全表DELETE语句,它带有一个恒为真的WHERE子句:
| DELETE FROM tbl_name WHERE 1; |
添加WHERE子句会强迫MySQL进行逐行删除,因为它必须计算出每一行的值来判断是否能够删除它。这个语句执行的速度很慢,但是它却保留了当前的AUTO_INCREMENT序号。
^[a-zA-Z0-9_\u4e00-\u9fa5]+$
Powered by hoder.org