首页 > 编程技术 > php

MySQL的数据类型和建库策略

发布时间:2016-11-25 16:44

无论是在小得可怜的免费数据库空间或是大型电子商务网站,合理的设计表结构、充分利用空间是十分必要的。这就要求我们对数据库系统的常用数据类型有充分的认识。下面我就将我的一点心得写出来跟大家分享。
一、数字类型。数字类型按照我的分类方法分为三类:整数类、小数类和数字类。
我所谓的“数字类”,就是指DECIMAL和NUMERIC,它们是同一种类型。它严格的说不是一种数字类型,因为他们实际上是将数字以字符串形式保存的;他的值的每一位(包括小数点)占一个字节的存储空间,因此这种类型耗费空间比较大。但是它的一个突出的优点是小数的位数固定,在运算中不会“失真”,所以比较适合用于“价格”、“金额”这样对精度要求不高但准确度要求非常高的字段。
小数类,即浮点数类型,根据精度的不同,有FLOAT(单精度)和DOUBLE(双精度)两种。它们的优势是精确度,FLOAT可以表示绝对值非常小、小到约 1.17E-38 (0.000...0117, 小数点后面有37个零)的小数,而DOUBLE更是可以表示绝对值小到约 2.22E-308 (0.000...0222, 小数点后面有307个零)的小数。FLOAT类型和DOUBLE类型占用存储空间分别是4字节和8字节。如果需要用到小数的字段,精度要求不高的,当然用FLOAT了!可是说句实在话,我们“民用”的数据,哪有要求精度那么高的呢?这两种类型至今我没有用过——我还没有遇到适合于使用它们的事例。
用的最多的,最值得精打细算的,是整数类型。从只占一个字节存储空间的TINYINT到占8个字节的BIGINT,挑选一个“够用”并且占用存储空间最小的类型是设计数据库时应该考虑的。TINYINT、SMALLINT、MEDIUMINT、INT和BIGINT占用存储空间分别为1字节、2字节、3字节、4字节和8字节,就无符号的整数而言,这些类型能表示的最大整数分别为255、65535、16777215、4294967295和18446744073709551615。如果用来保存用户的年龄(举例来说,数据库中保存年龄是不可取的),用TINYINT就够了;九城的《纵横》里,各项技能值,用SMALLINT也够了;如果要用作一个肯定不会超过16000000行的表的AUTO_INCREMENT的IDENTIFY字段,当然用 MEDIUMINT 不用 INT ,试想,每行节约一个字节,16000000行可以节约10兆多呢!
二、日期时间类型。
日期和时间类型比较简单,无非是 DATE、TIME、DATETIME、TIMESTAMP和YEAR等几个类型。只对日期敏感,而对时间没有要求的字段,就用DATE而不用DATETIME是不用说的了;单独使用时间的情况也时有发生——使用TIME;但最多用到的还是用DATETIME。在日期时间类型上没有什么文章可做,这里就不再详述。
特殊数据包括不能用前面所述的二进制、字符、Unicode、日期和时间、数字和货币数据类型表示的数据。
Microsoft® SQL Server™ 2000 包含四种特殊数据类型:
timestamp
用于表示 SQL Server 在一行上的活动顺序,按二进制格式以递增的数字来表示。当表中的行发生变动时,用从 @@DBTS 函数获得的当前数据库的时间戮值来更新时间戮。timestamp 数据与插入或修改数据的日期和时间无关。若要自动记录表中数据更改的时间,使用 datetime 或 smalldatetime 数据类型记录事件或触发器。
说明 在 SQL Serve 中 rowversion 是 timestamp 的同义词。
bit
bit 数据类型只能包括 0 或 1。可以用 bit 数据类型代表 TRUE 或 FALSE、YES 或 NO。例如,询问客户是否为初次访问的问题可存储在 bit 列中。
uniqueidentifier
以一个 16 位的十六进制数表示全局唯一标识符 (GUID)。当需要在多行中唯一标识某一行时可使用 GUID。例如,可使用 unique_ identifier 数据类型定义一个客户标识代码列,以编辑公司来自多个国家/地区的总的客户名录。
sql_variant
一种存储 SQL Server 所支持的各种数据类型(text、ntext、timestamp 和 sql_variant 除外)值的数据类型。
table
一种特殊的数据类型,存储供以后处理的结果集。table 数据类型只能用于定义 table 类型的局部变量或用户定义函数的返回值。
用户定义
允许使用用户定义数据类型,例如,product_code 可设计为基于 char 数据类型的两个大写字母后跟 5 位供应商号码的格式。

特殊数据类型是指那些不适合其它数据类型分类的数据类型。例如,若要将客户调查中"是"或"否"的值相应地用 1 或 0 进行存储,则可使用 bit 数据类型。Microsoft® SQL Server™ 2000 在该分类中有几个数据类型:
bit
bit 数据不必放在单引号中。它是与 SQL Server 的整型和数字数据相似的数字数据,但 bit 列只能存储 0 和 1。
sql_variant
SQL Server 中的 sql_variant 数据类型允许单个列、参数或变量存储不同数据类型的数据值。sql_variant 列的每个实例都记录数据值和描述该值的元数据:该值的基本数据类型、最大大小、小数位数、精度和排序规则。
下例中的第二个表包含一个 sql_variant 列:
CREATE TABLE ObjectTable
(ObjectID int
CONSTRAINT PKObjectTable PRIMARY KEY,
ObjectName nvarchar(80),
ObjectWeight decimal(10,3),
ObjectColor nvarchar(20)
)
CREATE TABLE VariablePropertyTable
(ObjectID int REFERENCES ObjectTable(ObjectID),
PropertyName nvarchar(100),
PropertyValue sql_variant,
CONSTRAINT PKVariablePropertyTable
PRIMARY KEY(ObjectID, PropertyName)
)
若要获得任何一个特定 sql_variant 实例的元数据信息,请使用 SQL_VARIANT_PROPERTY 函数。
table
table 数据类型类似是一个临时表,可以用于存储一个结果集以便以后处理。这种数据类型只能用于定义 table 类型的局部变量和用户定义函数的返回值。
一个 table 变量或返回值的定义包括列、数据类型、精度、每列的小数位数以及可选的 PRIMARY KEY、UNIQUE 和CHECK 约束。
存储在 table 变量中或用户定义函数返回值中的行的格式,必须在声明变量或创建函数时定义。其语法基于 CREATE
TABLE 的语法。例如:
DECLARE @TableVar TABLE
(Cola int PRIMARY KEY,
Colb char(3))
INSERT INTO @TableVar VALUES (1, 'abc')
INSERT INTO @TableVar VALUES (2, 'def')
SELECT * FROM @TableVar
GO
返回一个 table 的 table 变量和用户定义函数只能用于某些 SELECT 和 INSERT 语句,而且其中 UPDATE、DELETE 和
问题:从数据库中读出的中文均为“?”
解决方案:
Step 1:注册 Code Page使SQL Server支持中文
1.复制文件C_936.nls到系统目录下的system32目录
2.使用Regedit32.exe增加以下键:
location: HKEY_LOCAL_MACHINEsystemCurrentControlSetControlNlsCode
Page
value name: 936
value: C_936.NLS
location: HKEY_LOCAL_MACHINEsystemCurrentControlSetControlNlsLang
uage
value name: 0804
value: l_intl.nls
3.使用简体中文字符集重建SQL server的Master数据库
Step 2.
在ASP程序的开头中加入一行:
<%@ codepage=936 %>
这个解决方案好处是不用安装中文平台系统,又可以稳定运行NT(英文企业版较
稳定)

where优化主要是在SELECT中,因为他们最主要是在那里使用,但是同样的优化也可被用于DELETE和UPDATE语句。
但请注意,下面的优化并不是完全的。MYSQL实施了许多优化,但我没时间全部测试.
MySQL的一些优化列在下面:
删除不必要的括号:
((a AND b) AND c OR (((a AND b) AND (c AND d))))
-> (a AND b AND c) OR (a AND b AND c AND d)
常数调入:
(a<b AND b=c) AND a=5
-> b>5 AND b=c AND a=5
删除常数条件:
(B>=5 AND B=5) OR (B=6 AND 5=5) OR (B=7 AND 5=6)
-> B=5 OR B=6
索引使用的常数表达式仅计算一次。
在一个单个表上的没有一个WHERE的COUNT(*)直接从表中检索信息。当仅使用一个表时,对任何NOT NULL表达式也这样做。
无效常数表达式的早期检测。MySQL快速检测某些SELECT语句是不可能的并且不返回行。
如果你不使用GROUP BY或分组函数(COUNT()、MIN()……),HAVING与WHERE合并。
为每个子联结(sub join),构造一个更简单的WHERE以得到一个更快的WHERE计算并且也尽快跳过记录。
所有常数的表在查询中的在其他任何表之前被读出。
一个常数的表是:
一个空表或一个有1行的表。
与在一个UNIQUE索引、或一个PRIMARY KEY的WHERE子句一起使用的表,这里所有的索引部分使用一个常数表达式并且索引部分被定义为NOT NULL。
所有下列的表用作常数表:
mysql> SELECT * FROM t WHERE primary_key=1;
mysql> SELECT * FROM t1,t2 WHERE t1.primary_key=1 AND t2.primary_key=t1.id;
对联结表的最好联结组合是通过尝试所有可能性来找到:(。如果所有在ORDER BY和GROUP BY的列来自同一个表,那么当联结时,该表首先被选中。
如果你使用SQL_SMALL_RESULT,MySQL将使用一个在内存中的表。
如果有一个ORDER BY子句和一个不同的GROUP BY子句,或如果ORDER BY或GROUP BY包含不是来自联结队列中的第一个表的其他表的列,创建一个临时表。
因为DISTINCT被变换到在所有的列上的一个GROUP BY,DISTINCT与ORDER BY结合也将在许多情况下需要一张临时表。
每个表的索引被查询并且使用跨越少于30% 的行的索引。如果这样的索引没能找到,将使用一个快速的表扫描。
在一些情况下,MySQL能从索引中读出行,甚至不用查询数据文件。如果索引使用的所有列是数字的,那么只有索引树被用来解答查询。
标签:[!--infotagslink--]

您可能感兴趣的文章: