数据库

1.sql语句或问题

1.两表联查

SELECT vend_name,prod_name, prod_price
FROM Vendors, Products
WHERE Vendors.vend_id = Products.vend_id;

 

2.内连接

SELECT vend_name,prod_name, prod_price
FROM Vendors INNER JOIN Products
ON Vendors.vend_id = Products.vend_id;

 

此语句中的select与前面的select语句相同,但from子句不同。这里,两个表之间的关系是以inner join指定的部分from子句。在使用
这种语法时,联结条件用特定的on子句而不是where子句给出。传递给on的实际条件与传递给where的相同。

 

3.多表联查

SELECT prod_name,vend_name, prod_price, quantity
FROM OrderItems, Products, Vendors
WHERE Products.vend_id = Vendors.vend_id
AND OrderItems.prod_id = Products.prod_id
AND order_num = 20007;

 

性能考虑
DBMS(数据库管理系统)在运行时关联指定的每个表,以处理联结。这种处理可能非常耗费资源,因此应该注意,不要联结不必要的表。联结的表越多,性能下降越厉害。

 

4.子查询

SELECT cust_id
FROM Orders
WHERE order_num

 IN

(SELECT order_num
FROM OrderItems
WHERE prod_id = 'RGAN01');

 

5.联查并where

SELECT cust_name,cust_contact
FROM Customers, Orders, OrderItems
WHERE Customers.cust_id = Orders.cust_id
AND OrderItems.order_num = Orders.order_num
AND prod_id = 'RGAN01';

 

在这里,我们没有在嵌套子查询中使用它们,而是使用了两个联结来连接表。这里
有三个where子句条件。前两个关联联结中的表,后一个过滤产品RGAN01的数据。

 

多做实验
可以看到,执行任一给定的SQL操作一般不止一种方法。很少有绝对正确或绝对错误的方法。性能可能会受操作类型、所使用的DBMS、表中数据量、是否存在索引或键等条件的影响。因此,有必要试验不同的选择机制,找出最适合具体情况的方法。

 

6.多表联查(表别名)

SELECT cust_name,cust_contact
FROM Customers AS C, Orders AS O, OrderItems AS OI
WHERE C.cust_id = O.cust_id
AND OI.order_num = O.order_num
AND prod_id = 'RGAN01';

 

FROM子句中的三个表全都有别名。Customers AS C使用C作为Customers的别名,如此等等。这样,就可以使用省略的C而不用全
Customers

 

7.自连接 子查询 对比

 

SELECT cust_id,cust_name, cust_contact
FROM Customers
WHERE cust_name = (SELECT cust_name
FROM Customers
WHERE cust_contact = 'Jim Jones');

 

使用了子查询,内部的select语句做了一个简单检索,返回JimJones工作公司的cust_name。该名字用于外部查询的where子句中,以检索出为该公司工作的所有雇员

 

SELECT c1.cust_id,c1.cust_name, c1.cust_contact
FROM Customers AS c1, Customers AS c2
WHERE c1.cust_name = c2.cust_name
AND c2.cust_contact = 'Jim Jones';

 

自联结通常作为外部语句,用来替代从相同表中检索数据的使用子查询语句。虽然最终的结果是相同的,但许多DBMS处理联结远比处理子查询快得多。

 

8.自然连接

SELECT C.*,O.order_num, O.order_date,
OI.prod_id, OI.quantity, OI.item_price
FROM Customers AS C, Orders AS O, OrderItems AS OI
WHERE C.cust_id = O.cust_id
AND OI.order_num = O.order_num
AND prod_id = 'RGAN01';

 

通配符只对第一个表使用。所有其他列明确列出,所以没有重复的列被检索出来。
事实上,我们迄今为止建立的每个内联结都是自然联结,很可能永远都不会用到不是自然联结的内联结。

 

9.外连接

 

内连接

SELECTCustomers.cust_id, Orders.order_num
FROM Customers INNER JOIN Orders
ON Customers.cust_id = Orders.cust_id;

 

左外连接

SELECTCustomers.cust_id, Orders.order_num
FROM Customers LEFT OUTER JOIN Orders
ON Customers.cust_id = Orders.cust_id;

 

这条select语句使用了关键字outer join来指定联结类型(而不是在where子句中指定)。但是,与内联结关联两个表中的行不同的是,外联结还包括没有关联行的行。在使用outer join语法时,必须使用rightleft关键字指定包括其所有行的表(right指出的是outer join右边的表,而left指出的是outer join左边的表)。上面的例子使用left outer joinfrom子句左边的表(Customers表)中选择所有行。为了从右边的表中选择所有行,需要使用right outer join

 

右外连接

SELECTCustomers.cust_id, Orders.order_num
FROM Customers RIGHT OUTER JOIN Orders
ON Orders.cust_id = Customers.cust_id;

 

SQLite外联结
SQLite支持LEFTOUTER JOIN,但不支持RIGHTOUTER JOIN

 

外联结的类型
要记住,总是有两种基本的外联结形式:左外联结和右外联结。它们之间的唯一差别是所关联的表的顺序。换句话说,调
FROMWHERE子句中表的顺序,左外联结可以转换为右外联结。因此,这两种外联结可以互换使用,哪个方便就用哪个。

 

全外连接

SELECTCustomers.cust_id, Orders.order_num
FROM Orders FULL OUTER JOIN Customers
ON Orders.cust_id = Customers.cust_id;

 

FULL OUTER JOIN的支持
AccessMariaDBMySQLOpen OfficeBaseSQLite不支持FULL OUTER JOIN语法。

 

10.聚合函数连接

 

内连接 聚合 分组

SELECT Customers.cust_id,
COUNT(Orders.order_num)AS num_ord
FROMCustomers INNER JOIN Orders
ONCustomers.cust_id = Orders.cust_id
GROUPBY Customers.cust_id;

这条SELECT语句使用inner joinCustomersOrders表互相关联。group by子句按顾客分组数据,因此,函数调用count(Orders.order_num)对每个顾客的订单计数,将它作为num_ord返回。聚集函数也可以方便地与其他联结一起使用。

 

左外连接 聚合 分组

SELECT Customers.cust_id,
COUNT(Orders.order_num)AS num_ord
FROMCustomers LEFT OUTER JOIN Orders
ONCustomers.cust_id = Orders.cust_id
GROUPBY Customers.cust_id;

 

11.组合查询(复合查询)

 

使用union

SELECT cust_name, cust_contact, cust_email
FROMCustomers
WHEREcust_state IN ('IL','IN','MI')
UNION
SELECTcust_name, cust_contact, cust_email
FROMCustomers
WHEREcust_name = 'Fun4All';

 

两条select语句组成,之间用union关键字分隔。union指示DBMS执行这两条select语句,并把输出组合成一个查询结果集。

 

对比使用where

SELECT cust_name, cust_contact, cust_email
FROMCustomers
WHEREcust_state IN ('IL','IN','MI')
ORcust_name = 'Fun4All';

 

使用union可能比使用where子句更为复杂。但对于较复杂的过滤条件,或者从多个表(而不是一个表)中检索数据的情形,使用union可能会使处理更简单。

 

union

union必须由两条或两条以上的select语句组成,语句之间用关键字union分隔(因此,如果组合四条select语句,将要使用三个union关键字)。
union中的每个查询必须包含相同的列、表达式或聚集函数(不过,各个列不需要以相同的次序列出)。
列数据类型必须兼容:类型不必完全相同,但必须是DBMS可以隐含转换的类型(例如,不同的数值类型或不同的日期类型)

默认使用union时,重复的行会被自动取消,但是可以更改。

SELECT cust_name, cust_contact, cust_email
FROMCustomers
WHEREcust_state IN ('IL','IN','MI')
UNIONALL
SELECTcust_name, cust_contact, cust_email
FROMCustomers
WHEREcust_name = 'Fun4All';

使用UNION ALLDBMS不取消重复的行。

 

组合查询(排序)

SELECT cust_name, cust_contact, cust_email
FROMCustomers
WHEREcust_state IN ('IL','IN','MI')
UNION
SELECTcust_name, cust_contact, cust_email
FROMCustomers
WHEREcust_name = 'Fun4All'
ORDERBY cust_name, cust_contact;

 

DBMS将用它来排序所有select语句返回的所有结果。

 

12.添加数据

INSERT INTO Customers
VALUES('1000000006',
'ToyLand',
'123Any Street',
'NewYork',
'NY',
'11111',
'USA',
NULL,
NULL);

 

这种语法很简单,但并不安全,应该尽量避免使用。

 

INSERT INTO Customers(cust_id,
cust_name,
cust_address,
cust_city,
cust_state,
cust_zip,
cust_country,
cust_contact,
cust_email)
VALUES('1000000006',
'ToyLand',
'123Any Street',
'NewYork',
'NY',
'11111',
'USA',
NULL,
NULL);

 

与前一个insert语句的工作完全相同,但在表名后的括号里明确给出了列名。在插入行时,DBMS将用values列表中的相应值填入列表中的对应项。

因为提供了列名,values必须以其指定的次序匹配指定的列名,不一定按各列出现在表中的实际次序。其优点是,即使表的结构改变,这条insert语句仍然能正确工作。

 

13.复制表

SELECT *
INTOCustCopy
FROMCustomers;

 

这条select语句创建一个名为CustCopy的新表,并把Customers表的整个内容复制到新表中。因为这里使用的是select *,所以将在CustCopy表中创建(并填充)与Customers表的每一列相同的列。要想只复制部分的列,可以明确给出列名,而不是使用*通配符。

 

在使用select into时,任何select选项和子句都可以使用,包括wheregroup by
可利用联结从多个表插入数据;不管从多少个表中检索数据,数据都只能插入到一个表中。
select into是试验新SQL语句前进行表复制的很好工具。先进行复制,可在复制的数据上测试SQL代码,而不会影响实际的数据。

 

14.更新(修改)

UPDATE Customers
SETcust_email = 'kim@thetoystore.com'
WHEREcust_id = '1000000005';

 

update语句中可以使用子查询,使得能用select语句检索出的数据更新列数据。

 

要删除某个列的值,可设置它为NULL

UPDATE Customers
SETcust_email = NULL
WHEREcust_id = '1000000005';

这与保存空字符串很不同(空字符串用''表示,是一个值),而NULL表示没有值。

 

15.删除

DELETE FROM Customers
WHEREcust_id = '1000000006';

 

delete from要求指定从中删除数据的表名,where子句过滤要删除的行。

delete不需要列名或通配符。delete删除整行而不是删除列。要删除指定的列,请使用update语句。

delete语句从表中删除行,甚至是删除表中所有行。delete不删除表本身

 

如果想从表中删除所有行,不要使用delete。可使用truncate table语句,它完成相同的工作,而速度更快(因为不记录数据的变动)。

 

 

SQL程序员使用UPDATEDELETE时所遵循的重要原则。

除非确实打算更新和删除每一行,否则绝对不要使用不带where子句的updatedelete语句。
保证每个表都有主键(如果忘记这个内容,请参阅第12课),尽可能像where子句那样使用它(可以指定各主键、多个值或值的范围)。
updatedelete语句使用where子句前,应该先用select进行测试,保证它过滤的是正确的记录,以防编写的where子句不正确。
使用强制实施引用完整性的数据库(关于这个内容,请参阅第12课),这样DBMS将不允许删除其数据与其他表相关联的行。
有的DBMS允许数据库管理员施加约束,防止执行不带where子句的updatedelete语句。如果所采用的DBMS支持这个特性,应该使用它。

 

 

16.视图

SELECT cust_name, cust_contact
FROMCustomers, Orders, OrderItems
WHERECustomers.cust_id = Orders.cust_id
ANDOrderItems.order_num = Orders.order_num
ANDprod_id = 'RGAN01';

          ||

SELECT cust_name, cust_contact
FROMProductCustomers
WHEREprod_id = 'RGAN01';

 

视图的一些常见应用

重用SQL语句。
简化复杂的SQL操作。在编写查询后,可以方便地重用它而不必知道其基本查询细节。
使用表的一部分而不是整个表。
保护数据。可以授予用户访问表的特定部分的权限,而不是整个表的访问权限。
更改数据格式和表示。视图可返回与底层表的表示和格式不同的数据。

 

性能问题
因为视图不包含数据,所以每次使用视图时,都必须处理查询执行时需要的所有检索。如果你用多个联结和过滤创建了复杂的视图或者嵌套了视图,性能可能会下降得很厉害。因此,在部署使用了大量视图的应用前,应该进行测试。

 

关于视图创建和使用的一些最常见的规则和限制。
     1.与表一样,视图必须唯一命名(不能给视图取与别的视图或表相同的名字)。
     2.对于可以创建的视图数目没有限制。
     3.创建视图,必须具有足够的访问权限。这些权限通常由数据库管理人员授予。
     4.视图可以嵌套,即可以利用从其他视图中检索数据的查询来构造视图。所允许的嵌套层数在不同的DBMS中有所不同(嵌套视图可能会严重降低查询的性能,因此在产品环境中使用之前,应该对其进行全面测试)。
     5.许多DBMS禁止在视图查询中使用ORDER BY子句。
     6.有些DBMS要求对返回的所有列进行命名,如果列是计算字段,则需要使用别名。

     7.视图不能索引,也不能有关联的触发器或默认值。
     8.有些DBMS把视图作为只读的查询,这表示可以从视图检索数据,但不能将数据写回底层表。

     9.有些DBMS允许创建这样的视图,它不能进行导致行不再属于视图的插入或更新。例如有一个视图,只检索带有电子邮件地址的顾客。如果更新某个顾客,删除他的电子邮件地址,将使该顾客不再属于视图。这是默认行为,而且是允许的,但有的DBMS可能会防止这种情况发生。

 

创建视图

CREATE VIEW ProductCustomers AS
SELECTcust_name, cust_contact, prod_id
FROMCustomers, Orders, OrderItems
WHERECustomers.cust_id = Orders.cust_id
ANDOrderItems.order_num = Orders.order_num;

创建一个名为ProductCustomers的视图,它联结三个表。

 

SELECT cust_name, cust_contact
FROMProductCustomers
WHEREprod_id = 'RGAN01';

通过where子句从视图中检索特定数据。

 

 

17.存储过程

存储过程就是为以后使用而保存的一条或多条SQL语句。

 

好处:

     1.通过把处理封装在一个易用的单元中,可以简化复杂的操作

     2.防止错误保证了数据的一致性。

     3.简化对变动的管理。

     4.安全性,通过存储过程限制对基础数据的访问,减少了数据讹误(无意识的或别的原因所导致的数据讹误)的机会。

         5.存储过程通常以编译过的形式存储,所以DBMS处理命令的工作较少,提高了性能。

     6.存在一些只能用在单个请求中的SQL元素和特性,存储过程可以使用它们来编写功能更强更灵活的代码。

 

缺点:

     1.不同DBMS中的存储过程语法有所不同。

     2.编写存储过程比编写基本SQL语句复杂,需要更高的技能,更丰富的经验。因此,许多数据库管理员把限制存储过程的创建作为安全措施(主要受上一条缺陷的影响)。

 

执行存储过程

EXECUTE AddNewProduct( 'JTS01',
'StuffedEiffel Tower',
6.49,
'Plushstuffed toy with the text La
Tour Eiffel in red whiteand blue' );

这里执行一个名为AddNewProduct的存储过程,将一个新产品添加到Products表中。AddNewProduct有四个参数,分别是:供应商IDVendors表的主键)、产品名、价格和描述。这4个参数匹配存储过程中4个预期变量(定义为存储过程自身的组成部分)。此存储过程将新行添加到Products表,并将传入的属性赋给相应的列。

 

存储过程所完成的工作:
验证传递的数据,保证所有4个参数都有值;
生成用作主键的唯一ID
将新产品插入Products表,在合适的列中存储生成的主键和传递的数据。
这就是存储过程执行的基本形式。

 

创建存储过程

 

ORACLE(oracle)版

CREATE PROCEDURE MailingListCount (
ListCountOUT INTEGER
)

IS
v_rowsINTEGER;
BEGIN
  SELECT COUNT(*) INTO v_rows
  FROM Customers
  WHERE NOT cust_email IS NULL;
  ListCount := v_rows;
END;

这个存储过程有一个名为ListCount的参数。此参数从存储过程返回一个值而不是传递一个值给存储过程。关键字OUT用来指示这种行为。
Oracle支持IN(传递值给存储过程)、OUT(从存储过程返回值,如这里)、INOUT(既传递值给存储过程也从存储过程传回值)类型的参数。存储过程的代码括在BEGINEND语句中,这里执行一条简单的SELECT语句,它检索具有邮件地址的顾客。然后用检索出的行数设置ListCount(要传递的输出参数)。

 

var ReturnValue NUMBER
EXECMailingListCount(:ReturnValue);
SELECTReturnValue;

声明了一个变量来保存存储过程返回的任何值,然后执行存储过程,再使用select语句显示返回的值。

 

SQLServer版

CREATE PROCEDURE MailingListCount
AS
DECLARE@cnt INTEGER
SELECT@cnt = COUNT(*)
FROMCustomers
WHERENOT cust_email IS NULL;
RETURN@cnt;

此存储过程没有参数。调用程序检索SQL Server的返回代码支持的值。其中用DECLARE语句声明了一个名为@cnt的局部变量(SQLServer
所有局部变量名都以@起头);然后在SELECT语句中使用这个变量,让它包含COUNT()函数返回的值;最后,用RETURN @cnt语句将计数返
回给调用程序。

 

DECLARE @ReturnValue INT
EXECUTE@ReturnValue=MailingListCount;
SELECT@ReturnValue;

声明了一个变量来保存存储过程返回的任何值,然后执行存储过程,再使用select语句显示返回的值。

 

下面是另一个例子,在Orders表中插入一个新订单。此程序仅适用于SQLServer,但它说明了存储过程的某些用途和技术:

CREATE PROCEDURE NewOrder @cust_id CHAR(10)
AS
               -- Declare variable for order number (声明订单号的变量)
DECLARE @order_num INTEGER
               -- Get current highest order number(获取当前最高的订单号码)
SELECT @order_num=MAX(order_num)
FROM Orders
               -- Determine next order number(确定下一个订单号码)
SELECT @order_num=@order_num+1
               -- Insert new order(插入新订单)
INSERT INTO Orders(order_num, order_date, cust_id)

VALUES(@order_num, GETDATE(), @cust_id)
              -- Return order number退货号
RETURN@order_num;

Orders表中创建一个新订单。它只有一个参数,即下订单顾客的ID。订单号和订单日期这两列在存储过程中自动生成。代码首先声明一个局部变量来存储订单号。接着,检索当前最大订单号(使用MAX()函数)并增加1(使用select语句)。然后用INSERT语句插入由新生成的订单号、当前系统日期(用getdate()函数检索)和传递的顾客ID组成的订单。最后,用return @order_num返回订单号(处理订单物品需要它)。请注意,此代码加了注释,在编写存储过程时应该多加注释。

 

 

18.索引

创建索引

CREATE INDEX prod_name_ind
ONPRODUCTS (prod_name);

索引必须唯一命名。

索引的效率随表数据的增加或改变而变化。

最好定期检查索引,并根据需要对索引进行调整。

 

19.like操作符

SELECT prod_id, prod_name
FROMProducts
WHEREprod_name LIKE 'Fish%';

使用了搜索模式'Fish%'。在执行这条子句时,将检索任意以Fish起头的词。%告诉DBMS接受Fish之后的任意字符,不管它有多少字符。

NULL

通配符%看起来像是可以匹配任何东西,但有个例外,这就是null。子句WHERE prod_name LIKE '%'不会匹配产品名称为null的行

 

SELECT prod_id, prod_name
FROMProducts
WHEREprod_name LIKE '__ inch teddy bear';

%能匹配0个字符不同,_总是刚好匹配一个字符,不能多也不能少。

 

SELECT cust_contact
FROMCustomers
WHEREcust_contact LIKE '[JM]%'
ORDERBY cust_contact;

这一搜索模式使用了两个不同的通配符。[JM]匹配任何以方括号中字母开头的联系人名,它也只能匹
配单个字符。因此,任何多于一个字符的名字都不匹配。[JM]之后的%通配符匹配第一个字符之后的任意数目的字符,返回所需结果。
此通配符可以用前缀字符^(脱字号)来否定。

 

20.计算字段

SELECT prod_id,
quantity,
item_price,
quantity*item_priceAS expanded_price
FROMOrderItems
WHEREorder_num = 20008;

expanded_price列是一个计算字段,此计算为quantity*item_price。客户端应用现在可以使用这个新计算列,就像使用其他列一样。

圆括号可用来区分优先顺序

操 作 符

说 明

+

-

*

/

SELECT语句为测试、检验函数和计算提供了很好的方法。虽然SELECT通常用于从表中检索数据,但是省略了FROM子句后就是简单地访问
和处理表达式,例如SELECT 3 * 2;将返回6SELECT Trim(' abc ');将返回abcSELECTNow();使用Now()函数返回当前日期和时间。

可以根据需要使用SELECT语句进行检验。
 

2.数据库规范

三大范式:

         1NF:字段不可分。

         2NF:有主键,非主键字段依赖主键。

         3NF:非主键字段不能相互依赖

 

1.库名、表名、字段名:小写,下划线风格,不超过32个字符,必须见名知意,禁止拼音英文混用

 

2.库名、表明最后都要加上项目简写前缀:数据库csop,表csop_user。

 

3.把表做一个区分:

         实体表、业务表、关联表

 

4.实体表、业务表都应该有创建人、时间,修改人、时间

 

5.表示状态的固定长度的字段用int 不要用char ,int比 char效率高(例:男和女)

 

6.排序最好用char

 

7.一个表的字段不要超过20个,采用分标方式

 

8.表必须有主键,例如自增主键

 

解读:

 

a)主键递增,数据行写入可以提高插入性能,可以避免page分裂,减少表碎片提升空间和内存的使用

 

b)主键要选择较短的数据类型, Innodb引擎普通索引都会保存主键的值,较短的数据类型可以有效的减少索引的磁盘空间,提高索引的缓存效率

 

c) 无主键的表删除,在row模式的主从架构,会导致备库夯住

 

9.禁止使用外键,如果有外键完整性约束,需要应用程序控制

 

解读:外键会导致表与表之间耦合,update与delete操作都会涉及相关联的表,十分影响sql 的性能,甚至会造成死锁。高并发情况下容易造成数据库性能,大数据高并发业务场景数据库使用以性能优先

 

10.必须把字段定义为NOT NULL并且提供默认值

 

解读:

 

a)null的列使索引/索引统计/值比较都更加复杂,对MySQL来说更难优化

 

b)null 这种类型MySQL内部需要进行特殊处理,增加数据库处理记录的复杂性;同等条件下,表中有较多空字段的时候,数据库的处理性能会降低很多

 

c)null值需要更多的存储空,无论是表还是索引中每行中的null的列都需要额外的空间来标识

 

d)对null 的处理时候,只能采用is null或is not null,而不能采用=、in、<、<>、!=、not in这些操作符号。如:where name!=’shenjian’,如果存在name为null值的记录,查询结果就不会包含name为null值的记录

 

11.禁止使用TEXT、BLOB类型

 

解读:会浪费更多的磁盘和内存空间,非必要的大量的大字段查询会淘汰掉热数据,导致内存命中率急剧降低,影响数据库性能

 

12.禁止使用小数存储货币

 

解读:使用整数吧,小数容易导致钱对不上

 

13.必须使用varchar(20)存储手机号

 

解读:

 

a)涉及到区号或者国家代号,可能出现+-()

 

b)手机号会去做数学运算么?

 

c)varchar可以支持模糊查询,例如:like“138%”

 

14.禁止使用ENUM,可使用TINYINT代替

 

解读:

 

a)增加新的ENUM值要做DDL操作

 

b)ENUM的内部实际存储就是整数,你以为自己定义的是字符串?

 

15.单表索引建议控制在5个以内

 

单索引字段数不允许超过5个

 

解读:字段超过5个时,实际已经起不到有效过滤数据的作用了

 

16.禁止在更新十分频繁、区分度不高的属性上建立索引

 

解读:

 

a)更新会变更B+树,更新频繁的字段建立索引会大大降低数据库性能

 

b)“性别”这种区分度不大的属性,建立索引是没有什么意义的,不能有效过滤数据,性能与全表扫描类似

 

17.建立组合索引,必须把区分度高的字段放在前面

 

解读:能够更加有效的过滤数据

 

18.禁止使用SELECT *,只获取必要的字段,需要显示说明列属性

 

解读:

 

a)读取不需要的列会增加CPU、IO、NET消耗

 

b)不能有效的利用覆盖索引

 

c)使用SELECT *容易在增加或者删除字段后出现程序BUG

 

19.禁止使用INSERT INTO t_xxx VALUES(xxx),必须显示指定插入的列属性

 

解读:容易在增加或者删除字段后出现程序BUG

 

20.禁止使用属性隐式转换

 

解读:SELECT uid FROMt_user WHERE phone=13812345678 会导致全表扫描,而不能命中phone索引,猜猜为什么?(这个线上问题不止出现过一次)

 

21.禁止在WHERE条件的属性上使用函数或者表达式

 

解读:SELECT uid FROMt_user WHERE from_unixtime(day)>='2017-02-15' 会导致全表扫描

 

正确的写法是:SELECT uid FROMt_user WHERE day>= unix_timestamp('2017-02-15 00:00:00')

 

22.禁止负向查询,以及%开头的模糊查询

 

解读:

 

a)负向查询条件:NOT、!=、<>、!<、!>、NOT IN、NOT LIKE等,会导致全表扫描

 

b)%开头的模糊查询,会导致全表扫描

 

23.禁止大表使用JOIN查询,禁止大表使用子查询

 

解读:会产生临时表,消耗较多内存与CPU,极大影响数据库性能

 

24.禁止使用OR条件,必须改为IN查询

 

解读:旧版本Mysql的OR查询是不能命中索引的,即使能命中索引,为何要让数据库耗费更多的CPU帮助实施查询优化呢?

 

25.应用程序必须捕获SQL异常,并有相应处理

 

总结

 

大数据量高并发的互联网业务,极大影响数据库性能的都不让用。

 

 

 

---------------------------------------------入职后注意------------------------------------------------

行为规范

 

禁止使用应用程序配置文件内的帐号手工访问线上数据库

 

禁止非DBA对线上数据库进行写操作,修改线上数据需要提交工单,由DBA执行,提交的SQL语句必须经过测试

 

分配非DBA以只读帐号,必须通过VPN+跳板机访问授权的从库

 

开发、测试、线上环境隔离

 

为什么要制定行为规范的军规呢,大伙的公司是不是有这样的情况:

 

任何研发、测试都有连接线上数据库的帐号?

 

是不是经常有这类误操作?

 

(1)本来只想update一条记录,where条件搞错,update了全部的记录

 

(2)本来只想delete几行记录,结果删多了,四下无人,再insert回去

 

(3)以为drop的是测试库,结果把线上库drop掉了

 

(4)以为操作的是分库x,结果SecureCRT开窗口太多,操作成了分库y

 

(5)写错配置文件,压力测试压到线上库了,生成了N多脏数据

 

 

无数的事情,结果就是打电话给DBA,让他们帮忙擦屁股。

 

 

所谓的“业务灵活性”都是扯淡,为什么要有行为规范?不让你带刀,不是限制你,而是保护你的安全。要相信DBA是专业的,让专业的人干专业的事情。别把DBA看做你的对立面,多和他们沟通业务场景,沟通请求读写比,沟通访问模式,他们真的能帮助到你,这是我带DBA团队的一些感触。

 

 

 

---------------------------------------------入职后注意------------------------------------------------

 

 

3.数据库比较

1.关系型数据库

关系型数据库,是指采用了关系模型来组织数据的数据库。

简单来说,关系模型指的就是二维表格模型,而一个关系型数据库就是由二维表及其之间的联系所组成的一个数据组织。

 

1.关系模型中常用的概念

 

    关系:可以理解为一张二维表,每个关系都具有一个关系名,就是通常说的表名

    元组:可以理解为二维表中的一行,在数据库中经常被称为记录

    属性:可以理解为二维表中的一列,在数据库中经常被称为字段

    域:属性的取值范围,也就是数据库中某一列的取值限制

    关键字:一组可以唯一标识元组的属性,数据库中常称为主键,由一个或多个列组成

    关系模式:指对关系的描述。其格式为:关系名(属性1,属性2, ... ... ,属性N),在数据库中成为表结构

 

2.关系型数据库的优点

 

    容易理解:二维表结构是非常贴近逻辑世界的一个概念,关系模型相对网状、层次等其他模型来说更容易理解

    使用方便:通用的SQL语言使得操作关系型数据库非常方便

    易于维护:丰富的完整性(实体完整性、参照完整性和用户定义的完整性)大大减低了数据冗余和数据不一致的概率

 

3.关系型数据库的缺点

 

          扩展困难:由于存在类似Join这样多表查询机制,使得数据库在扩展方面很艰难;
         读写慢:这种情况主要发生在数据量达到一定规模时由于关系型数据库的系统逻辑非常复杂,使得其非常容易发生死锁等的并发问题,所以导致其读写速度下滑非常严重;
         成本高:企业级数据库的License价格很惊人,并且随着系统的规模,而不断上升;
         有限的支撑容量:现有关系型解决方案还无法支撑Google这样海量的数据存储;

 

4.关系型数据库的瓶颈

 

   ---高并发读写需求

 

网站的用户并发性非常高,往往达到每秒上万次读写请求,对于传统关系型数据库来说,硬盘I/O是一个很大的瓶颈

 

   ---海量数据的高效率读写

 

网站每天产生的数据量是巨大的,对于关系型数据库来说,在一张包含海量数据的表中查询,效率是非常低的

 

   ---高扩展性和可用性

 

在基于web的结构当中,数据库是最难进行横向扩展的,当一个应用系统的用户量和访问量与日俱增的时候,数据库却没有办法像web server和app server那样简单的通过添加更多的硬件和服务节点来扩展性能和负载能力。对于很多需要提供24小时不间断服务的网站来说,对数据库系统进行升级和扩展是非常痛苦的事情,往往需要停机维护和数据迁移。

[

 

5.对网站来说,关系型数据库的很多特性不再需要了

 

   ---事务一致性

 

关系型数据库在对事物一致性的维护中有很大的开销,而现在很多web2.0系统对事物的读写一致性都不高

 

   ---读写实时性

 

对关系数据库来说,插入一条数据之后立刻查询,是肯定可以读出这条数据的,但是对于很多web应用来说,并不要求这么高的实时性,比如发一条消息之后,过几秒乃至十几秒之后才看到这条动态是完全可以接受的

 

   ---复杂SQL,特别是多表关联查询

 

任何大数据量的web系统,都非常忌讳多个大表的关联查询,以及复杂的数据分析类型的复杂SQL报表查询,特别是SNS类型的网站,从需求以及产品阶级角度,就避免了这种情况的产生。往往更多的只是单表的主键查询,以及单表的简单条件分页查询,SQL的功能极大的弱化了

 

在关系型数据库中,导致性能欠佳的最主要原因是多表的关联查询,以及复杂的数据分析类型的复杂SQL报表查询。为了保证数据库的ACID特性,我们必须尽量按照其要求的范式进行设计,关系型数据库中的表都是存储一个格式化的数据结构。每个元组字段的组成都是一样,即使不是每个元组都需要所有的字段,但数据库会为每个元组分配所有的字段,这样的结构可以便于标语表之间进行链接等操作,但从另一个角度来说它也是关系型数据库性能瓶颈的一个因素。

 

 

2.NoSQL(非关系型数据库)

随着互联网的不断发展,各种类型的应用层出不穷,所以导致在这个云计算的时代,对技术提出了更多的需求,主要体现在下面这四个方面:
1. 低延迟的读写速度:应用快速地反应能极大地提升用户的满意度;
2. 支撑海量的数据和流量:对于搜索这样大型应用而言,需要利用PB级别的数据和能应对百万级的流量;
3. 大规模集群的管理:系统管理员希望分布式应用能更简单的部署和管理;
4. 庞大运营成本的考量:IT经理们希望在硬件成本、软件成本和人力成本能够有大幅度地降低;

 

NoSQL用于指代那些非关系型的,分布式的,且一般不保证遵循ACID原则的数据存储系统。

 

NoSQL(NoSQL= Not Only SQL ),意即“不仅仅是SQL”,是一项全新的数据库革命性运动。NoSQL的拥护者们提倡运用非关系型的数据存储。大多数数据库技术不能保证支持ACID(原子性、一致性、隔离性和持久性),而且大部分技术都是开源项目,这些技术作为整体被称为NoSQL。

 

1.NoSQL的优点


1. 简单的扩展:典型例子是Cassandra,由于其架构是类似于经典的P2P,所以能通过轻松地添加新的节点来扩展这个集群;
2. 快速的读写:主要例子有Redis,由于其逻辑简单,而且纯内存操作,使得其性能非常出色,单节点每秒可以处理超过10万次读写操作;
3. 低廉的成本:这是大多数分布式数据库共有的特点,因为主要都是开源软件,没有昂贵的License成本;
 

2.NoSQL的缺点


1. 不提供对SQL的支持:如果不支持SQL这样的工业标准,将会对用户产生一定的学习和应用迁移成本;
2. 支持的特性不够丰富:现有产品所提供的功能都比较有限,大多数NoSQL数据库都不支持事务,也不像MS SQLServer和Oracle那样能提供各种附加功能,比如BI和报表等;
3. 现有产品的不够成熟:大多数产品都还处于初创期,和关系型数据库几十年的完善不可同日而语;

 

 

3.一般将NoSQL数据库分为四大类

         键值(Key-Value)存储数据库、列存储数据库、文档型数据库和图形(Graph)数据库。

 

 

 

4.NoSQL的特征

 

 

 

5.常见的NoSQL数据库

 

 

 

6.NoSQL的使用场景

         1、数据模型比较简单;

         2、需要灵活性更强的IT系统;

         3、对数据库性能要求较高;

         4、不需要高度的数据一致性;

         5、对于给定key,比较容易映射复杂值的环境。

 

 

3.比较(mysql、oracle、mongdb、rides)

1.MySQL

优点:

         体积小、速度快、低成本、开源,一般中小型网站的开发都选择 MySQL 作为网站数据库。

         MySql可运行在不同的操作系统下,方便移植。

         MySql有一个非常灵活而且安全的权限和口令系统。当客户与MySql服务器连接时,他们之间所有的口令传送被加密,而且MySql支持主机认证。

         MySql支持大型的数据库。虽然对于用PHP编写的网页来说只要能够存放上百条以上的记录数据就足够了,但MySql可以方便地支持上千万条记录的数据库。作为一个开放源代码的数据库,MySql可以针对不同的应用进行相应的修改。

         MySql拥有一个非常快速而且稳定的基于线程的内存分配系统,可以持续使用面不必担心其稳定性。事实上,MySql的稳定性足以应付一个超大规模的数据库。  

         MySql的核心程序采用完全的多线程编程支持多处理器。线程是轻量级的进程,它可以灵活地为用户提供服务,而不过多的系统资源。

         强大的查询功能。MySql支持查询的SELECT和WHERE语句的全部运算符和函数,并且可以在同一查询中混用来自不同数据库的表,从而使得查询变得快捷和方便。

         MySQL 能够提供很多不同的使用者界面,包括命令行客户端操作,网页浏览器,以及各式各样的程序语言界面
  PHP为MySql提供了强力支持,PHP中提供了一整套的MySql函数,对MySql进行了全方位的支持。

         SQL兼容性:mysql遵循SQL:2003标准,并且有自己的扩展

 

 

缺点:

         MySQL最大的缺点是其安全系统,主要是复杂而非标准,另外只有到调用mysqladmin来重读用户权限时才发生改变。

         MySQL的另一个主要的缺陷之一是缺乏标准的RI(ReferentialIntegrity-RI)机制;Rl限制的缺乏(在给定字段域上的一种固定的范围限制)可以通过大量的数据类型来补偿。

         MySQL没有一种存储过程(Stored Procedure)语言,这是对习惯于企业级数据库的程序员的最大限制。

         MySQL对存储过程和触发器支持不够良好。

         使用myisam配置,如果你不慎损坏数据库,结果可能会导致所有的数据丢失

         MySQL不支持热备份。

 

2.Oracle

Oracle数据库系统是目前世界上流行的关系数据库管理系统,系统可移植性好、使用方便、功能强,适用于各类大、中、小、微机环境。它是一种高效率、可靠性好的 适应高吞吐量的数据库解决方案。

优点:
         开放性:Oracle 能所有主流平台上运行(包括windows)完全支持所有工业标准采用完全开放策略使客户选择适合解决方案对开发商全力支持;
         可伸缩性,并行性:Oracle 并行服务器通过使组结点共享同簇工作来扩展windownt能力提供高用性和高伸缩性簇解决方案windowsNT能满足需要用户把数据库移UNIXOracle并行服务器对各种UNIX平台集群机制都有着相当高集成度;
         安全性:获得最高认证级别的ISO标准认证。 
         性能:Oracle 性能高 保持开放平台下TPC-D和TPC-C世界记录;(ORACLE体系先进,所以性能优异)
         客户端支持及应用模式:Oracle 多层次网络计算支持多种工业标准用ODBC、JDBC、OCI等网络客户连接
         使用风险:Oracle 长时间开发经验完全向下兼容得广泛应用地风险低

         采用标准的SQL结构化查询语言。
         具有丰富的开发工具,覆盖开发周期的各阶段。(ORACLE的可用性非常强,oracle的组件功能全)

         分布优化查询功能。

 

缺点:
对硬件的要求很高;
价格比较昂贵;
管理维护麻烦一些;
操作比较复杂,需要技术含量较高;

数据库连接要慢些,最好用连接池;

数据库崩溃后回复很麻烦,因为他把很多东西放在内存里;
 

3.MongoDB

MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。他支持的数据结构非常松散,是类似json的bjson格式,因此可以存储比较复杂的数据类型。Mongo最大的特点是他支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。它的特点是高性能、易部署、易使用,存储数据非常方便。

 

优点:

         内置GridFS,支持大容量存储;

         第三方支持丰富;

         性能优越;(在使用场合下,千万级别的文档对象,近10G的数据,对有索引的ID的查询不会比mysql慢,而对非索引字段的查询,则是全面胜出。 mysql实际无法胜任大数据量下任意字段的查询)

 

 

 

4.Redis

Redis 是一个开源的使用ANSIC语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

优点:

         1. 支持多种数据类型

    包括set,zset,list,hash,string这五种数据类型,操作非常方便。比如,如果你在做好友系统,查看自己的好友关系,如果采用其他的key-value系统,则必须把对应的好友拼接成字符串,然后在提取好友时,再把value进行解析,而redis则相对简单,直接支持list的存储(采用双向链表或者压缩链表的存储方式)。

         2.持久化存储

    作为一个内存数据库,最担心的,就是万一机器死机,数据会消失掉。redi使用rdb和aof做数据的持久化存储。主从数据同时,生成rdb文件,并利用缓冲区添加新的数据更新操作做对应的同步。

         3.丰富的特性

    pub/sub,key过期策略,事务,支持多个DB等。

         4.性能很好

    由于是全内存操作,所以读写性能很好。

         5.支持主从复制,主机会自动将数据同步到从机,实现读写分离

 

缺点:

         1.由于是内存数据库,所以,单台机器,存储的数据量,跟机器本身的内存大小。虽然redis本身有key过期策略,但是还是需要提前预估和节约内存。如果内存增长过快,需要定期删除数据。

         2.如果进行完整重同步,由于需要生成rdb文件,并进行传输,会占用主机的CPU,并会消耗现网的带宽。不过redis2.8版本,已经有部分重同步的功能,但是还是有可能有完整重同步的。比如,新上线的备机

         3.修改配置文件,进行重启,将硬盘中的数据加载进内存,时间比较久。在这个过程中,redis不能

提供服务。

         4. Redis较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。

         5. Redis不具备自动容错和恢复功能,主机从机的宕机都会导致前端部分读写请求失败,需要等待机器重启或者手动切换前端的IP才能恢复。

 

 

6.Mongdb与Mysql的比较

 

 

 

 

 

4.数据库优化

 

(1)必须使用InnoDB存储引擎

 

解读:支持事务、行级锁、并发性能更好、CPU及内存缓存页优化使得资源利用率更高

(2)必须使用UTF8字符集        

UTF-8mb4是UTF8的超集,emoji表情以及部分不常见汉字在utf8下会                                                               表现为乱码,故需要升级至utf8mb4。 但不节省空间

 

解读:万国码,无需转码,无乱码风险,节省空间

 

(3)数据表、数据字段必须加入中文注释

 

解读:N年后谁tm知道这个r1,r2,r3字段是干嘛的

 

(4)禁止使用存储过程、视图、触发器、Event

 

解读:高并发大数据的互联网业务,架构设计思路是“解放数据库CPU,将计算转移到服务层”,并发量大的情况下,这些功能很可能将数据库拖死,业务逻辑放到服务层具备更好的扩展性,能够轻易实现“增机器就加性能”。数据库擅长存储与索引,CPU计算还是上移吧

 

(5)禁止存储大文件或者大照片

 

解读:为何要让数据库做它不擅长的事情?大文件和照片存储在文件系统,数据库里存URI多好

 

(6)选取最适用的字段属性

 

解读:MySQL可以很好的支持大数据量的存取,但是一般说来,数据库中的表越小,在它上面执行的查询也就会越快。因此,在创建表的时候,为了获得更好的性能,我们可以将表中字段的宽度设得尽可能小。

 

(7) 在可能的情况下,应该尽量把字段设置为NOTNULL

 

解读:这样在将来执行查询的时候,数据库不用去比较NULL值。

 

(8) 使用连接(JOIN)来代替子查询(Sub-Queries)

 

解读:如果使用连接(JOIN)..来完成这个查询工作,速度将会快很多。

 

(9) 使用联合(UNION)来代替手动创建的临时表

 

解读:union查询,它可以把需要使用临时表的两条或更多的select查询合并的一个查询中。在客户端的查询会话结束的时候,临时表会被自动删除,从而保证数据库整齐、高效。使用union来创建查询的时候,我们只需要用UNION作为关键字把多个select语句连接起来就可以了,要注意的是所有select语句中的字段数目要想同。

 

(10)事务

 

解读:可以保持数据库中数据的一致性和完整性。

         当多个用户同时使用相同的数据源时,它可以利用锁定数据库的方法来为用户提供一种安全的访问方式,这样可以保证用户的操作不被其它的用户所干扰。

 

(11)锁定表

 

解读:事务是维护数据库完整性的一个非常好的方法,但却因为它的独占性,有时会影响数据库的性能,尤其是在很大的应用系统中。如果一个数据库系统只有少数几个用户来使用,事务造成的影响不会成为一个太大的问题;但假设有成千上万的用户同时访问一个数据库系统,例如访问一个电子商务网站,就会产生比较严重的响应延迟。我们可以通过锁定表的方法来获得更好的性能。

 

(12)外键

 

解读:锁定表的方法可以维护数据的完整性,但是它却不能保证数据的关联性。这个时候我们就可以使用外键。

 

(13) 使用索引

 

解读:索引是提高数据库性能的常用方法,它可以令数据库服务器以比没有索引快得多的速度检索特定的行,尤其是在查询语句当中包含有MAX(),MIN()和ORDERBY这些命令的时候,性能提高更为明显。索引应建立在那些将用于JOIN,WHERE判断和ORDERBY排序的字段上。尽量不要对数据库中某个含有大量重复的值的字段建立索引。有可能降低数据库的性能。

 

(14) 优化的查询语句

 

解读:最好是在相同类型的字段间进行比较的操作;

         在建有索引的字段上尽量不要使用函数进行操作。

         在搜索字符型字段时,我们有时会使用LIKE关键字和通配符,这种做法虽然简单,但却也是以牺牲系统性能为代价的。

         应该注意避免在查询中让MySQL进行自动类型转换,因为转换过程也会使索引变得不起作用。

 

(15) 设计规范化表,消除数据冗余

 

解读:三大范式...  (数据库规范)

 

(16) 适当的冗余,增加计算列

 

解读:数据库设计的实用原则是:在数据冗余和处理速度之间找到合适的平衡点 

         满足范式的表一定是规范化的表,但不一定是最佳的设计。很多情况下会为了提高数据库的运行效率,常常需要降低范式标准:适当增加冗余,达到以空间换时间的目的。

 

(17)传说中的‘三少原则’

 

解读:1.数据库的表越少越好

         2.表的字段越少越好

         3.字段中的组合主键、组合索引越少越好

当然这里的少是相对的,是减少数据冗余的重要设计理念。

 

(18)常见的一些方法 sql语句的注意

 

解读:      

         一、操作符优化、

                   1. IN、NOT IN 操作符

                            IN和EXISTS 性能有外表和内表区分的,但是在大数据量的表中推荐用EXISTS 代替IN 。

                      Not IN 不走索引的是绝对不能用的,可以用NOT EXISTS 代替。

                   2. IS NULL 或IS NOT NULL操作

                            索引是不索引空值的,所以这样的操作不能使用索引,可以用其他的办法处理,例如:数                     字类型,判断大于0,字符串类型设置一个默认值,判断是否等于默认值即可

                   3. <> 操作符(不等于) 

                            不等于操作符是永远不会用到索引的,因此对它的处理只会产生全表扫描。 用其它相同功           能的操作运算代替,如 a<>0 改为 a>0 or a<0    a<>’’ 改为 a>’’ 

                   4. 用全文搜索搜索文本数据,取代like搜索

                            全文搜索始终优于like搜索:

                          (1)全文搜索让你可以实现like不能完成的复杂搜索,如搜索一个单词或一个短语,搜索            一个与另一个单词或短语相近的单词或短语,或者是搜索同义词;

                          (2)实现全文搜索比实现like搜索更容易(特别是复杂的搜索);

 

    二、 SQL语句优化

           1、在查询中不要使用  select * 

           2. 尽量写WHERE子句

           3. 注意SELECT INTO后的WHERE子句

           4.对于聚合查询,

        可以用HAVING子句进一步限定返回的行

           5. 避免使用临时表

                            (1)除非却有需要,否则应尽量避免使用临时表,相反,可以使用表变量代替;

                         (2)大多数时候(99%),表变量驻扎在内存中,因此速度比临时表更快,临时表驻扎在TempDb                数据库中,因此临时表上的操作需要跨数据库通信,速度自然慢。

           6.减少访问数据库的次数:

                            程序设计中最好将一些常用的全局变量表放在内存中或者用其他的方式减少数据库的访问            次数

           7.尽量少做重复的工作

 

    三、where使用原则

                   1. 在where子句中应把最具限制性的条件放在最前面。

                   2. where子句中字段的顺序应和索引中字段顺序一致。

                   3. select field3,field4 from tb where field1='sdf' 快
                      select * from tb where field1='sdf' 慢,
                      因为后者在索引扫描后要多一步ROWID表访问。


                      select field3,field4 from tb where field1>='sdf' 快
                      select field3,field4 from tb where field1>'sdf' 慢
                      因为前者可以迅速定位索引。


                      select field3,field4 from tb where field2 like 'R%' 快
                      select field3,field4 from tb where field2 like '%R' 慢,
                      因为后者不使用索引。

                   4.使用函数如:
                      select field3,field4 from tb where upper(field2)='RMN'不使用索引。
                         如果一个表有两万条记录,建议不使用函数;如果一个表有五万条以上记录,严格禁止使                     用函数!两万条记录以下没有限制。

 

 

 

分区分表:

 

1) 增强可用性:如果表的某个分区出现故障,表在其他分区的数据仍然可用;

 

2) 维护方便:如果表的某个分区出现故障,需要修复数据,只修复该分区即可;

 

3) 均衡I/O:可以把不同的分区映射到磁盘以平衡I/O,改善整个系统性能;

 

4) 改善查询性能:对分区对象的查询可以仅搜索自己关心的分区,提高检索速度。

 

 

数据库的读写分离

 

读写分离,基本的原理是让主数据库处理事务性增、改、删操作(INSERT、UPDATE、DELETE),而从数据库处理SELECT查询操作。数据库复制被用来把事务性操作导致的变更同步到集群中的从数据库。

 

 

什么是分库分表?

 

把一个很大的库(表)的数据分到几个库(表)中,每个库(表)的结构都相同,但他们可能分布在不同的数据库实例,甚至不同的物理机器上,以达到降低单库(表)数据量,提高访问性能的目的。

 

分库分表往往是业务层实施的,分库分表后,为了满足某些特定业务功能,往往需要rd修改代码。

 

 

为什么要分库、分表、读写分?

 

单表的数据量限制,当单表数据量到一定条数之后数据库性能会显著下降。数据多了之后,对数据库的读、写就会很多。分库减少单台数据库的压力。接触过几个分库分表的系统,都是通过主键进行散列分裤分表的。这类数据比较特殊,主键就是唯一的获取该条信息的主要途径。比如:京东的订单、财付通的交易记录等。。。该类数据的用法,就是通过订单号、交易号来查询该笔订单、交易。

 

 

------------------------不能使用

 

什么是mysql的分区表?

 

回答:所有数据还在一个表中,但物理存储根据一定的规则放在不同的文件中。这个是mysql支持的功能,业务rd代码无需改动。

 

看上去分区表很帅气,为什么大部分互联网还是更多的选择自己分库分表来水平扩展咧?

 

回答:

    分区表,分区键设计不太灵活,如果不走分区键,很容易出现全表锁

    一旦数据量并发量上来,如果在分区表实施关联,就是一个灾难

    自己分库分表,自己掌控业务场景与访问模式,可控。分区表,研发写了一个sql,都不确定mysql是怎么玩的,不太可控

 

------------------------不能使用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值