101

我已经使用Microsoft SQL Server很多年了,但直到最近才开始在我的 Web 应用程序中使用MySQL,我渴望知识。

为了继续一长串的“隐藏功能”问题,我想知道 MySQL 的任何隐藏或方便的功能,这将有望提高我对这个开源数据库的了解。

4

20 回答 20

161

既然你提出了赏金,我会分享我来之不易的秘密......

一般来说,我今天调优的所有 SQL 都需要使用子查询。来自 Oracle 数据库世界,我认为理所当然的事情与 MySQL 不同。我对 MySQL 调优的阅读使我得出结论,MySQL 在优化查询方面落后于 Oracle。

虽然大多数 B2C 应用程序所需的简单查询可能适用于 MySQL,但 Intelligence Reporting 所需的大多数聚合报告类型的查询似乎需要相当多的计划和重新组织 SQL 查询以指导 MySQL 更快地执行它们。

行政:

max_connections是并发连接数。默认值为 100 个连接(自 5.0 起为 151 个)- 非常小。

笔记:

连接占用内存,您的操作系统可能无法处理大量连接。

Linux/x86 的 MySQL 二进制文件允许您拥有多达 4096 个并发连接,但自编译二进制文件的限制通常较小。

设置 table_cache 以匹配您打开的表和并发连接的数量。观察 open_tables 值,如果它增长很快,您将需要增加它的大小。

笔记:

前面的 2 个参数可能需要大量打开的文件。20+max_connections+table_cache*2 可以很好地估计您的需求。Linux 上的 MySQL 有一个 open_file_limit 选项,设置这个限制。

如果您有复杂的查询,sort_buffer_size 和 tmp_table_size 可能非常重要。值将取决于查询复杂性和可用资源,但建议的起点分别为 4Mb 和 32Mb。

注意:这些是“每个连接”值,包括 read_buffer_size、read_rnd_buffer_size 和其他一些值,这意味着每个连接都可能需要此值。因此,在设置这些参数时,请考虑您的负载和可用资源。例如 sort_buffer_size 仅在 MySQL 需要进行排序时才分配。注意:小心不要耗尽内存。

如果您建立了许多连接(即没有持久连接的网站),您可以通过将 thread_cache_size 设置为非零值来提高性能。16 是很好的价值开始。增加该值,直到您的 threads_created 增长速度不会很快。

首要的关键:

每个表只能有一个 AUTO_INCREMENT 列,它必须被索引,并且不能有 DEFAULT 值

KEY 通常是 INDEX 的同义词。当在列定义中给出键属性 PRIMARY KEY 时,也可以仅将其指定为 KEY。这是为了与其他数据库系统兼容而实现的。

PRIMARY KEY 是唯一索引,其中所有键列必须定义为 NOT NULL

如果 PRIMARY KEY 或 UNIQUE 索引仅包含一个具有整数类型的列,您还可以在 SELECT 语句中将该列称为“_rowid”。

在 MySQL 中,PRIMARY KEY 的名称是 PRIMARY

目前,只有 InnoDB (v5.1?) 表支持外键。

通常,您在创建表时创建所需的所有索引。任何声明为 PRIMARY KEY、KEY、UNIQUE 或 INDEX 的列都将被索引。

NULL 表示“没有值”。要测试 NULL,您不能使用算术比较运算符,例如 =、< 或 <>。请改用 IS NULL 和 IS NOT NULL 运算符:

NO_AUTO_VALUE_ON_ZERO 禁止自动递增为 0,以便只有 NULL 生成下一个序列号。如果 0 已存储在表的 AUTO_INCREMENT 列中,则此模式很有用。(顺便说一句,不推荐存储 0。)

要更改用于新行的 AUTO_INCREMENT 计数器的值:

ALTER TABLE mytable AUTO_INCREMENT = value; 

或 SET INSERT_ID = 值;

除非另有说明,否则该值将以: 1000000 开头,或者这样指定:

...) ENGINE=MyISAM 默认字符集=latin1 AUTO_INCREMENT=1

时间戳:

TIMESTAMP 列的值从当前时区转换为 UTC 进行存储,从 UTC 转换为当前时区进行检索。

http://dev.mysql.com/doc/refman/5.1/en/timestamp.html 对于表中的一个 TIMESTAMP 列,您可以将当前时间戳指定为默认值和自动更新值。

在 WHERE 子句中使用其中一种类型时要注意的一件事是,最好使用 WHERE datecolumn = FROM_UNIXTIME(1057941242) 而不是 WHERE UNIX_TIMESTAMP(datecolumn) = 1057941242。后者不会利用索引在那一栏。

http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html

 UNIX_TIMESTAMP() 
 FROM_UNIXTIME() 
 UTC_DATE()
 UTC_TIME()
 UTC_TIMESTAMP()

如果您在 MySQL 中将日期时间转换为 unix 时间戳:
然后将 24 小时添加到它:
然后将其转换回日期时间,它会神奇地失去一个小时!

这是正在发生的事情。将 unix 时间戳转换回日期时间时,会考虑时区,并且恰好在 2006 年 10 月 28 日至 29 日之间,我们关闭了夏令时并损失了一个小时。

从 MySQL 4.1.3 开始,CURRENT_TIMESTAMP()、CURRENT_TIME()、CURRENT_DATE() 和 FROM_UNIXTIME() 函数返回连接的当前时区中的值,该时区可用作 time_zone 系统变量的值。此外,UNIX_TIMESTAMP() 假定其参数是当前时区中的日期时间值。

当前时区设置不会影响 UTC_TIMESTAMP() 等函数显示的值或 DATE、TIME 或 DATETIME 列中的值。

注意:ON UPDATE在字段更改时更新 DateTime 如果 UPDATE 导致没有字段被更改,则 DateTime 不会更新!

此外,第一个 TIMESTAMP 默认始终为 AUTOUPDATE,即使未指定也是如此

在使用 Dates 时,我几乎总是使用 Julian Date,因为数据数学是一个简单的加减整数的问题,而 Seconds since Midnight 出于同样的原因。我很少需要比秒更细粒度的时间分辨率。

这两个都可以存储为一个 4 字节整数,如果空间真的很紧,可以将 UNIX 时间(自 1970 年 1 月 1 日以来的秒数)作为无符号整数组合到 2106 年左右,如下所示:

' 24 小时内的秒数 = 86400

' 有符号整数 max val = 2,147,483,647 - 可以保存 68 年的秒数

' 无符号整数 max val = 4,294,967,295 - 可以保存 136 年的秒数

二进制协议:

MySQL 4.1 引入了一种二进制协议,允许以本机格式发送和返回非字符串数据值,而无需与字符串格式进行转换。(非常有用)

另外,mysql_real_query() 比 mysql_query() 快,因为它不调用 strlen() 对语句字符串进行操作。

http://dev.mysql.com/tech-resources/articles/4.1/prepared-statements.html 二进制协议支持服务器端准备好的语句,并允许以本机格式传输数据值。在 MySQL 4.1 的早期版本中,二进制协议经历了相当多的修订。

您可以使用 IS_NUM() 宏来测试字段是否具有数字类型。将类型值传递给 IS_NUM(),如果字段为数字,则计算结果为 TRUE:

需要注意的一件事是,如果您对二进制数据进行转义并记住 MySQL需要反斜杠和引号字符被转义,则可以在常规查询中发送二进制数据。因此,这是插入较短的二进制字符串(例如加密/加盐密码)的一种非常简单的方法。

主服务器:

http://www.experts-exchange.com/Database/MySQL/Q_22967482.html

http://www.databasejournal.com/features/mysql/article.php/10897_3355201_2

授予复制奴隶到 slave_user 由“slave_password”识别

#Master Binary Logging Config  STATEMENT causes replication 
              to be statement-based -  default

log-bin=Mike
binlog-format=STATEMENT
server-id=1            
max_binlog_size = 10M
expire_logs_days = 120    


#Slave Config
master-host=master-hostname
master-user=slave-user
master-password=slave-password
server-id=2

二进制日志文件必须阅读:

http://dev.mysql.com/doc/refman/5.0/en/binary-log.html

http://www.mydigitallife.info/2007/10/06/how-to-read-mysql-binary-log-files-binlog-with-mysqlbinlog/

http://dev.mysql.com/doc/refman/5.1/en/mysqlbinlog.html

http://dev.mysql.com/doc/refman/5.0/en/binary-log.html

http://dev.mysql.com/doc/refman/5.1/en/binary-log-setting.html

您可以使用 RESET MASTER 语句删除所有二进制日志文件,或使用 PURGE MASTER 删除其中的一部分

--result-file=binlog.txt TrustedFriend-bin.000030

正常化:

http://dev.mysql.com/tech-resources/articles/intro-to-normalization.html

UDF 函数

http://www.koders.com/cpp/fid10666379322B54AD41AEB0E4100D87C8CDDF1D8C.aspx

http://souptonuts.sourceforge.net/readme_mysql.htm

数据类型:

http://dev.mysql.com/doc/refman/5.1/en/storage-requirements.html

http://www.informit.com/articles/article.aspx?p=1238838&seqNum=2

http://bitfilm.net/2008/03/24/saving-bytes-efficient-data-storage-mysql-part-1/

需要注意的一点是,在具有 CHAR 和 VARCHAR 的混合表上,mySQL 会将 CHAR 更改为 VARCHAR

RecNum integer_type UNSIGNED NOT NULL AUTO_INCREMENT, PRIMARY KEY (RecNum)

根据标准 SQL 和 ISO 8601 规范,MySQL 始终以年份表示日期

杂项:

关闭一些 MySQl 功能将导致更小的数据文件和更快的访问。例如:

--datadir 将指定数据目录和

--skip-innodb 将关闭 inno 选项并为您节省 10-20M

更多在这里 http://dev.mysql.com/tech-resources/articles/mysql-c-api.html

下载第 7 章 - 免费

InnoDB 是事务性的,但随之而来的是性能开销。我发现 MyISAM 表足以满足我 90% 的项目。非事务安全表 (MyISAM) 有自己的几个优点,所有这些都是因为:

没有交易开销:

快多了

降低磁盘空间要求

执行更新所需的内存更少

每个 MyISAM 表都存储在磁盘上的三个文件中。这些文件的名称以表名开头,并具有指示文件类型的扩展名。.frm 文件存储表格格式。数据文件具有 .MYD (MYData) 扩展名。索引文件具有 .MYI (MYIndex) 扩展名。

这些文件可以原封不动地复制到存储位置,而无需使用耗时的 MySQL 管理员备份功能(还原也是如此)

诀窍是制作这些文件的副本,然后 DROP 表。当你把文件放回去时,MySQl 会识别它们并更新表跟踪。

如果您必须备份/恢复,

恢复备份或从现有转储文件导入可能需要很长时间,具体取决于您在每个表上拥有的索引和主键的数量。您可以通过使用以下内容来修改原始转储文件来显着加快此过程:

SET AUTOCOMMIT = 0;
SET FOREIGN_KEY_CHECKS=0;

.. your dump file ..

SET FOREIGN_KEY_CHECKS = 1;
COMMIT;
SET AUTOCOMMIT = 1;

要大大提高重新加载的速度,请添加 SQL 命令 SET AUTOCOMMIT = 0; 在转储文件的开头,并添加 COMMIT;命令到最后。

默认情况下,自动提交是打开的,这意味着转储文件中的每个插入命令都将被视为一个单独的事务,并在下一个启动之前写入磁盘。如果不添加这些命令,将大型数据库重新加载到 InnoDB 可能需要很多小时......

MySQL 表中行的最大大小为 65,535 字节

MySQL 5.0.3 及更高版本中 VARCHAR 的有效最大长度 = 最大行大小(65,535 字节)

VARCHAR 值在存储时不会被填充。按照标准 SQL,在存储和检索值时保留尾随空格。

MySQL 中的 CHAR 和 VARCHAR 值在比较时不考虑尾随空格。

如果整个记录是固定大小的,使用 CHAR 只会加快您的访问速度。也就是说,如果您使用任何可变大小的对象,您不妨将它们全部设为可变大小。在还包含 VARCHAR 的表中使用 CHAR 不会提高速度。

自 MySQL 5.0.3 起,255 个字符的 VARCHAR 限制已提高到 65535 个字符

仅 MyISAM 表支持全文搜索。

http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html

BLOB 列没有字符集,排序和比较是基于列值中字节的数值

如果未启用严格 SQL 模式,并且您为 BLOB 或 TEXT 列分配的值超过了列的最大长度,则该值将被截断以适应并生成警告。

有用的命令:

检查严格模式:SELECT @@global.sql_mode;

关闭严格模式:

SET @@global.sql_mode='';

SET @@global.sql_mode='MYSQL40'

或删除: sql-mode="STRICT_TRANS_TABLES,...

显示来自的列mytable

SELECT max(namecount) AS virtualcolumnFROM mytable ORDER BY virtualcolumn

http://dev.mysql.com/doc/refman/5.0/en/group-by-hidden-fields.html

http://dev.mysql.com/doc/refman/5.1/en/information-functions.html#function_last-insert-id last_insert_id()

为您获取当前线程中插入的最后一行的 PK max(pkcolname) 为您提供最后一个 PK。

注意:如果表为空 max(pkcolname) 返回 1 mysql_insert_id() 将本机 MySQL C API 函数 mysql_insert_id() 的返回类型转换为 long 类型(在 PHP 中命名为 int)。

如果您的 AUTO_INCREMENT 列具有 BIGINT 列类型,则 mysql_insert_id() 返回的值将不正确。相反,在 SQL 查询中使用内部 MySQL SQL 函数 LAST_INSERT_ID()。

http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_last-insert-id

请注意,当您尝试将数据插入表中时会出现错误:

Unknown column ‘the first bit of data what you want to put into the table‘ in ‘field list’

使用类似的东西

INSERT INTO table (this, that) VALUES ($this, $that)

这是因为你没有在你试图粘贴到表格中的值周围加上任何撇号。因此,您应该将代码更改为:

INSERT INTO table (this, that) VALUES ('$this', '$that') 

提醒 `` 用于定义 MySQL 字段、数据库或表,而不是值;)

查询期间失去与服务器的连接:

http://dev.mysql.com/doc/refman/5.1/en/gone-away.html

http://dev.mysql.com/doc/refman/5.1/en/packet-too-large.html

http://dev.mysql.com/doc/refman/5.0/en/server-parameters.html

http://dev.mysql.com/doc/refman/5.1/en/show-variables.html

http://dev.mysql.com/doc/refman/5.1/en/option-files.html

http://dev.mysql.com/doc/refman/5.1/en/error-log.html

调优查询

http://www.artfulsoftware.com/infotree/queries.php?&bw=1313

嗯,这应该足以赚取我认为的奖金......许多小时和许多项目的成果,以及一个很棒的免费数据库。我主要使用 MySQL 在 Windows 平台上开发应用程序数据服务器。我不得不理顺的最糟糕的烂摊子是

终极 MySQL 遗留数据库噩梦

这需要一系列应用程序来使用这里提到的许多技巧将表格处理成有用的东西。

如果您发现这非常有帮助,请通过投票表示感谢。

另请查看我的其他文章和白皮书:www.coastrd.com

于 2009-03-01T23:32:24.907 回答
22

MySQL 的一个不那么隐藏的特性是它不太擅长与 SQL 兼容,嗯,不是真正的错误,但是,更多的陷阱...... :-)

于 2008-12-15T16:21:00.690 回答
21

用于找出缓存中当前有哪些表的命令:

mysql> SHOW open TABLES FROM test;
+----------+-------+--------+-------------+
| DATABASE | TABLE | In_use | Name_locked |
+----------+-------+--------+-------------+
| test     | a     |      3 |           0 |
+----------+-------+--------+-------------+
1 row IN SET (0.00 sec)

(来自MySQL 性能博客

于 2008-12-15T16:30:24.823 回答
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 
于 2008-12-15T16:22:43.840 回答
11

inet_ntoa()我特别喜欢 MySQL 对和的内置支持inet_aton()。它使处理表中的 IP 地址变得非常简单(至少只要它们只是 IPv4 地址!)

于 2008-12-22T10:20:28.727 回答
11

我喜欢on duplicate key(AKA upsert,merge)懒惰创建的各种计数器:

insert into occurances(word,count) values('foo',1),('bar',1) 
  on duplicate key cnt=cnt+1

您可以在一个查询中插入多行,并立即处理每一行的重复索引。

于 2009-06-21T20:35:03.703 回答
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

Feature / Gotcha:无需在 GROUP BY 列表中包含非聚合表达式

大多数 RDBMS 强制执行符合 SQL92 的 GROUP BY,它要求 SELECT 列表中的所有非聚合表达式都出现在 GROUP BY 中。在这些 RDBMS-es 中,此语句:

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-es 中,您必须修改 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 列将包含无意义的内容(也就是说,在所有语言百分比中,将随机选择百分比的可用值之一,或者至少在您的控制之外。

见:揭穿集团的神话

于 2009-06-22T11:31:12.730 回答
7

客户端中的“寻呼机”命令

例如,如果您的结果中有 10,000 行并想要查看它们(这假定“less”和“tee”命令可用,这在 Linux 下通常是这种情况;在 Windows YMMV 中。)

pager less
select lots_of_stuff FROM tbl WHERE clause_which_matches_10k_rows;

你会在“less”文件查看器中找到它们,这样你就可以很好地翻页、搜索等。

pager tee myfile.txt
select a_few_things FROM tbl WHERE i_want_to_save_output_to_a_file;

将方便地写入文件。

于 2009-06-22T06:14:55.957 回答
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
于 2009-02-27T20:52:40.033 回答
4

不是隐藏功能,但仍然有用:http: //mtop.sourceforge.net/

于 2009-03-06T00:54:37.547 回答
3

以下是我的一些技巧 - 我在我的博客(链接)中写了关于它们的博客

  1. 声明变量时不需要使用“@”符号。
  2. 您必须使用分隔符(默认为';')来划分语句的结尾 -链接
  3. 如果您尝试在 MS-SQL 2005 和 mySQL 之间移动数据,则需要跳过一些障碍 -链接
  4. 在 mySQL 中进行区分大小写的匹配 -链接
于 2009-03-03T06:19:04.750 回答
3

如果您要使用大型和/或高事务 InnoDb 数据库学习并理解“SHOW INNODB STATUS” Mysql 性能博客,它将成为您的朋友。

于 2009-03-03T06:45:16.077 回答
3

如果使用 cmdline Mysq,您可以使用尖叫/感叹号与命令行交互(在 Linux 机器上 - 不确定在 Windows 上是否有等效效果)。例如:

\! cat file1.sql

将显示 file1.sql 的代码。要将您的语句和查询保存到文件中,请使用 tee 工具

\T filename

要关闭此功能,请使用 \t

最后,要运行您已经保存的脚本,请使用“源文件名”。当然,正常的替代方法是在命令行启动mysql时直接输入脚本名:

    mysql -u root -p < case1.sql

希望这对某人有用!

编辑:只记得另一个 - 从命令行调用 mysql 时,您可以使用 -t 开关,以便输出为表格格式 - 对一些查询来说是一个真正的好处(当然,如这里其他地方提到的,使用 \G 终止查询也是在这方面有帮助)。更多关于各种开关的命令行工具

刚刚找到了一种更改排序顺序的巧妙方法(通常使用案例...)如果您想更改排序顺序(可能按 1, 4, 3 ,2 而不是 1, 2, 3 排序, 4) 您可以在 Order by 子句中使用字段函数。例如

按字段排序(sort_field,1,4,3,2)

于 2009-06-20T13:18:28.940 回答
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)
于 2011-09-21T12:14:54.120 回答
2

mysqlsla - 非常常用的慢查询日志分析工具之一。自您上次推出慢查询日志以来,您可以看到前 10 个最差查询。它还可以告诉您 BAD 查询被触发的次数以及它在服务器上花费的总时间。

于 2009-06-22T11:53:25.383 回答
2

实际上记录在案,但很烦人:错误日期和其他错误输入的自动转换。

在 MySQL 5.0.2 之前,MySQL 允许非法或不正确的数据值,并强制它们为数据输入的合法值。在 MySQL 5.0.2 及更高版本中,这仍然是默认行为,但您可以更改服务器 SQL 模式以选择更传统的错误值处理方式,以便服务器拒绝它们并中止它们发生的语句。

至于日期:有时当 MySQL 不将输入调整为附近的有效日期,而是将其存储为0000-00-00根据定义无效的日期时,您会很“幸运”。但是,即使那样,您也可能希望 MySQL 失败,而不是默默地为您存储此值。

于 2009-07-12T12:20:12.423 回答
2

内置SQL Profiler

于 2011-03-16T14:57:53.797 回答
1

InnoDB 默认将所有表存储在一个永远不会收缩的全局表空间中。

您可以使用innodb_file_per_tablewhich 将每个表放在一个单独的表空间中,当您删除表或数据库时,该表空间将被删除。

提前为此做好计划,因为否则您必须转储和恢复数据库以回收空间。

使用每表表空间

于 2009-06-05T08:08:23.850 回答
1

如果您在日期时间列中插入空字符串值“”,MySQL 将保留该值作为 00/00/0000 00:00:00。不像Oracle,它将保存空值。

于 2011-08-01T12:04:00.640 回答
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'
于 2011-10-08T17:15:48.283 回答