我多年来一直与Microsoft SQL Server合作,但最近才开始在我的网络应用程序中使用MySQL,而且我渴望知识。
继续"hidden feature" questions的长行,我想知道MySQL的任何隐藏或方便的功能,这将有望提高我对这个开源数据库的了解。
答案 0 :(得分:161)
答案 1 :(得分:22)
MySQL的一个不那么隐藏的功能是,它不是真的很擅长SQL兼容,好吧,不是真的错误,但是,更多gotchas ...: - )
答案 2 :(得分:21)
找出当前缓存中的表的命令:
mysql> SHOW open TABLES FROM test;
+----------+-------+--------+-------------+
| DATABASE | TABLE | In_use | Name_locked |
+----------+-------+--------+-------------+
| test | a | 3 | 0 |
+----------+-------+--------+-------------+
1 row IN SET (0.00 sec)
答案 3 :(得分:15)
找出谁在做什么的命令:
mysql> show processlist;
show processlist;
+----+-------------+-----------------+------+---------+------+----------------------------------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+-------------+-----------------+------+---------+------+----------------------------------+------------------+
| 1 | root | localhost:32893 | NULL | Sleep | 0 | | NULL |
| 5 | system user | | NULL | Connect | 98 | Waiting for master to send event | NULL |
| 6 | system user | | NULL | Connect | 5018 | Reading event from the relay log | NULL |
+-----+------+-----------+---------+---------+-------+-------+------------------+
3 rows in set (0.00 sec)
您可以使用以下命令终止进程:
mysql>kill 5
答案 4 :(得分:11)
我特别喜欢MySQL对inet_ntoa()
和inet_aton()
的内置支持。它使表中的IP地址处理变得非常简单(至少只要它们只是IPv4地址!)
答案 5 :(得分:11)
我喜欢on duplicate key
(AKA upsert,merge)为懒惰创建的各种计数器:
insert into occurances(word,count) values('foo',1),('bar',1)
on duplicate key cnt=cnt+1
您可以在一个查询中插入多行,并立即处理每个行的重复索引。
答案 6 :(得分:10)
再次 - 不是真正隐藏的功能,但非常方便:
<强>功能强>
轻松抓住DDL:
SHOW CREATE TABLE CountryLanguage
输出:
CountryLanguage | CREATE TABLE countrylanguage (
CountryCode char(3) NOT NULL DEFAULT '',
Language char(30) NOT NULL DEFAULT '',
IsOfficial enum('T','F') NOT NULL DEFAULT 'F',
Percentage float(4,1) NOT NULL DEFAULT '0.0',
PRIMARY KEY (CountryCode,Language)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
功能:GROUP_CONCAT()聚合函数 每个细节创建其参数的串联字符串,并通过连接每个组进行聚合。
示例1:简单
SELECT CountryCode
, GROUP_CONCAT(Language) AS List
FROM CountryLanguage
GROUP BY CountryCode
输出:
+-------------+------------------------------------+
| CountryCode | List |
+-------------+------------------------------------+
| ABW | Dutch,English,Papiamento,Spanish |
. ... . ... .
| ZWE | English,Ndebele,Nyanja,Shona |
+-------------+------------------------------------+
示例2:多个参数
SELECT CountryCode
, GROUP_CONCAT(
Language
, IF(IsOfficial='T', ' (Official)', '')
) AS List
FROM CountryLanguage
GROUP BY CountryCode
输出:
+-------------+---------------------------------------------+
| CountryCode | List |
+-------------+---------------------------------------------+
| ABW | Dutch (Official),English,Papiamento,Spanish |
. ... . ... .
| ZWE | English (Official),Ndebele,Nyanja,Shona |
+-------------+---------------------------------------------+
示例3:使用自定义分隔符
SELECT CountryCode
, GROUP_CONCAT(Language SEPARATOR ' and ') AS List
FROM CountryLanguage
GROUP BY CountryCode
输出:
+-------------+----------------------------------------------+
| CountryCode | List |
+-------------+----------------------------------------------+
| ABW | Dutch and English and Papiamento and Spanish |
. ... . ... .
| ZWE | English and Ndebele and Nyanja and Shona |
+-------------+----------------------------------------------+
示例4:控制列表元素的顺序
SELECT CountryCode
, GROUP_CONCAT(
Language
ORDER BY CASE IsOfficial WHEN 'T' THEN 1 ELSE 2 END DESC
, Language
) AS List
FROM CountryLanguage
GROUP BY CountryCode
输出:
+-------------+------------------------------------+
| CountryCode | List |
+-------------+------------------------------------+
| ABW | English,Papiamento,Spanish,Dutch, |
. ... . ... .
| ZWE | Ndebele,Nyanja,Shona,English |
+-------------+------------------------------------+
功能:包含多个表达式的COUNT(DISTINCT)
您可以在COUNT(DISTINCT ...)表达式中使用多个表达式来计算组合数。
SELECT COUNT(DISTINCT CountryCode, Language) FROM CountryLanguage
功能/陷阱:无需在GROUP BY列表中包含非聚合表达
大多数RDBMS-es强制执行符合SQL92的GROUP BY,这要求SELECT列表中的所有非聚合表达式都出现在GROUP BY中。在这些RDBMS中,这句话:
SELECT Country.Code, Country.Continent, COUNT(CountryLanguage.Language)
FROM CountryLanguage
INNER JOIN Country
ON CountryLanguage.CountryCode = Country.Code
GROUP BY Country.Code
无效,因为SELECT列表包含未出现在GROUP BY列表中的非聚合列Country.Continent。在这些RDBMS中,您必须修改GROUP BY列表以读取
GROUP BY Country.Code, Country.Continent
或者您必须向Country.Continent添加一些无意义的聚合,例如
SELECT Country.Code, MAX(Country.Continent), COUNT(CountryLanguage.Language)
现在,问题是,逻辑上没有任何东西要求Country.Continent应该进行聚合。请参阅Country.Code是Country表的主键。 Country.Continent也是Country表中的一列,因此在功能上依赖于主键Country.Code的定义。因此,对于每个不同的Country.Code,Country.Continent中必须只存在一个值。如果你意识到这一点,那么你就会意识到聚合它是没有意义的(只有一个值,正确),也不是按它分组(因为它不会使结果更加独特,因为你已经分组了pk)
无论如何 - MySQL允许您在SELECT列表中包含非聚合列,而无需将它们也添加到GROUP BY子句中。
问题在于,如果您碰巧使用非聚合列,MySQL不会保护您。所以,像这样的查询:
SELECT Country.Code, COUNT(CountryLanguage.Language), CountryLanguage.Percentage
FROM CountryLanguage
INNER JOIN Country
ON CountryLanguage.CountryCode = Country.Code
GROUP BY Country.Code
将在没有投诉的情况下执行,但CountryLanguage.Percentage列将包含无意义(也就是说,在所有语言百分比中,百分比的其中一个可用值将随机选取或至少在您控制之外
答案 7 :(得分:7)
客户端中的“pager”命令
如果您的结果中有10,000行,并希望查看它们(这假定“less”和“tee”命令可用,这通常是在Linux下的情况;在Windows YMMV中。)
pager less
select lots_of_stuff FROM tbl WHERE clause_which_matches_10k_rows;
你会在“较少”的文件查看器中获取它们,这样你就可以很好地浏览它们,搜索等。
另外
pager tee myfile.txt
select a_few_things FROM tbl WHERE i_want_to_save_output_to_a_file;
将方便地写入文件。
答案 8 :(得分:6)
有些事情你可能会感兴趣:
<query>\G -- \G in the CLI instead of the ; will show one column per row
explain <query>; -- this will show the execution plan for the query
答案 9 :(得分:4)
不是隐藏的功能,但仍然有用:http://mtop.sourceforge.net/
答案 10 :(得分:3)
如果使用cmdline Mysq,您可以使用尖叫/感叹号与命令行进行交互(在Linux机器上 - 不确定是否对Windows有相同的效果)。例如:
\! cat file1.sql
将显示file1.sql的代码。要将语句和查询保存到文件,请使用tee facility
\T filename
将其关闭使用\ t
最后要运行已保存的脚本,请使用“source filename”。当然,正常的替代方法是在从命令行启动mysql时指向脚本名称:
mysql -u root -p < case1.sql
希望对某人有用!
编辑:只记得另一个 - 当从命令行调用mysql时,你可以使用-t开关,使输出为表格格式 - 带有一些查询的真正好处(虽然当然用其他地方提到的\ G终止查询)这方面也有帮助)。关于各种开关Command Line Tool 的更多内容刚刚找到一种改变排序顺序的简洁方法(通常使用Case ...) 如果要更改排序顺序(可能按1,4,3,2而不是1,2,3,4排序),可以使用Order by子句中的字段函数。 例如
按字段排序(sort_field,1,4,3,2)
答案 11 :(得分:3)
我认为这不是针对MySQL的,而是让我感到高兴:
而不是写
WHERE (x.id > y.id) OR (x.id = y.id AND x.f2 > y.f2)
你可以写
WHERE (x.id, x.f2) > (y.id, y.f2)
答案 12 :(得分:3)
如果您打算使用大型和/或高交易量的InnoDb数据库来学习和理解“SHOW INNODB STATUS”Mysql Performance Blog,它将成为您的朋友。
答案 13 :(得分:3)
以下是我的一些提示 - 我在博客上发表了关于他们的博文(Link)
答案 14 :(得分:2)
mysqlsla - 最常用的慢查询日志分析工具之一。自上次推出慢查询日志以来,您可以看到前10个重要查询。它还可以告诉您BAD查询被触发的次数以及它在服务器上花费的总时间。
答案 15 :(得分:2)
实际上是documented,但非常烦人:错误日期和其他错误输入的自动转换。
在MySQL 5.0.2之前,MySQL可以容忍非法或不正确的数据值,并强制它们为数据输入的合法值。在MySQL 5.0.2及更高版本中,这仍然是默认行为,但您可以更改服务器SQL模式以选择更传统的错误值处理方式,以便服务器拒绝它们并中止它们出现的语句。
至于日期:当MySQL没有将输入调整到附近的有效日期时,有时你会“幸运”,而是将其存储为0000-00-00
,根据定义,它是无效的。但是,即便如此,您可能希望MySQL失败,而不是默默地为您存储此值。
答案 16 :(得分:2)
内置SQL Profiler。
答案 17 :(得分:1)
默认情况下,InnoDB将所有表存储在一个全局表空间中,永不缩小。
您可以使用innodb_file_per_table
将每个表放在一个单独的表空间中,当您删除表或数据库时,这些表空间将被删除。
提前计划,因为你必须转储和恢复数据库,否则回收空间。
答案 18 :(得分:1)
如果在datetime列中插入空字符串值“”,MySQL将保留该值为00/00/0000 00:00:00。与Oracle不同,后者将保存空值。
答案 19 :(得分:1)
在使用大型数据集和DATETIME字段的基准测试期间,执行此查询的速度总是较慢:
SELECT * FROM mytable
WHERE date(date_colum) BETWEEN '2011-01-01' AND ''2011-03-03';
比这种方法:
SELECT * FROM mytable
WHERE date_column BETWEEN '2011-01-01 00:00:00' AND '2011-03-03 23:59:59'