DROP PROCEDURE`t_girl``sp_split_table`$
。的CREATE PROCEDURE`t_girl``sp_split_table`()
开始
声明所做的诠释默认0
申报v_user_name VARCHAR(20)默认“,
申报v_table_name VARCHAR (64)默认“
-获取所有用户的名称。
user_name的选择USER_NAME t_group组申报cur1光标
-处理错误或警告。
宣布继续完成1329集= 1的处理程序
-打开游标。
开放cur1
而<>1
不
取到v_user_name cur1
如果没有这样做,那么
-获取表名。
设置v_table_name = CONCAT('t_group_',v_user_name),
-创建新的额外的表
集@ stmt的= CONCAT('创建表',v_table_name“像t_group')
S1 @ stmt的准备
执行S1
降准备S1
-数据加载到
stmt的CONCAT(“的插入',v_table_name,'SELECT *从t_group其中user_name =''',v_user_name,'')
准备S1 @ stmt的
执行S1
降准备S1
结束,如果
结束而
-关闭游标。
密切cur1
-从内存中自由变量的
设置@ stmt的= NULL
完$ $
界定符
2,试验表。
我们当前用一个有一千万条记录的表来做测试。
MySQL的教程 >SELECT COUNT(*)从t_group
+ --------- +
|计数(*)|
+ --------- +
| 10388608 |
+ ----- ----- +
1集行(0.00秒)
表结构
的MySQL>DESC t_group
+ ----------- + ------------------ + - + - ---- + ------ + ---------------- +
|场|类型| NULL |重点|中|额外|
+ ----------- + ------------------ + ------ + - - + ------ + ---------------- +
| ID | INT(10)无符号|无|的PRI | NULL | AUTO_INCREMENT |
|钱|十进制(10,2)| NO | | | |
| USER_NAME | VARCHAR(20)号的MUL | |
| | CREATE_TIME |时间戳| NO | | CURRENT_TIMESTAMP的| |
+ - --------- + ------------------ + ------ + ----- + ------- ------------ + ---------------- +
4行集(0.00秒)
索引情况。
mysql的显示指数从 表| Non_unique | Key_name | Seq_in_index | COLUMN_NAME |校勘基数Sub_part |盒装NULL | Index_type |评论 t_group | 0 |小学| 1 | ID | | 10388608 |空|空| | B树| | | t_group | | idx_user_name | 1 | USER_NAME | | |空|空| | B树| | | t_group | 1 | idx_combination1 | 1 | USER_NAME | | |空|空| | B树| | | t_group | | idx_combination1 | 2 |钱| | 3776 |空|空| | B树| 集行(0.00秒)
注:
idx_combination1这个索引什么必须的因为要对USER_NAME来集团此时属于松散索引扫描当然完了后你可以干掉她
idx_user_name
MYSQL>选择t_group USER_NAME 1 USER_NAME组
+ ----------- +
| USER_NAME |
+ ---- +
|大卫
| | 狮子座
| | 利维娅|
|露西|
|撒拉|
|西蒙|
|索尼
| | 晴天|
+ ---- +
8集行(0.00秒)
所以结果调表应该是这样的。
mysql的像“t_group_%>SHOW TABLES
+ ------------------------------ +
| Tables_in_t_girl(t_group_%)|
+ ---------- +
| t_group_david
| | t_group_leo
| | t_group_livia
| | t_group_lucy |
| t_group_sarah
| t_group_simon |
| t_group_sony
| | t_group_sunny时加入|
+ ------------------------------ +
8行集( 0.00秒)
3,对比结果。
MySQL的>SELECT COUNT(*)从t_group的USER_NAME ='国宝'
+ ---------- +
|计数(*)|
+ --------- +
| 1298576 |
+ ---------- +
1行集(1.71秒)
执行了将近2秒。
MySQL的>SELECT COUNT(*)从t_group_david的
+ --------- +
|计数(*)|
+ --------- +
| 1298576 |
+ --- ---- +
1集行(0.00秒)
几乎什么瞬间的
MySQL的>SELECT COUNT(*)从t_group其中user_name <>“国宝”
+ --------- +
|计数(*)|
+ --------- +
| 9090032 |
+ --------- +
1集行(9.26秒)
执行了将近10秒,可以想象,这个什么实际的项目大全-宜配网什么不能忍受的。
MySQL的选择(SELECT COUNT(*)从t_group) - (SELECT COUNT(*)来自t_group_david)总额
+ --------- +
|总时加入|
+ --------- +
| 9090032 |
+ --- --- +
1集行(0.00秒)
几乎什么瞬间的
我们来看看聚集函数。
对于原表的 *** 作。
MYSQL>选择分(钱),MAX(钱)从t_group其中user_name ='国宝'
+ ------------ + ------------ +
| MIN (钱)| MAX(钱)|
+ ------------ + ------------ +
| -6.41 | 500.59 |
+ ------- ----- + ------------ +
1集行(0.00秒)
最小,最大值都是全索引扫描。所以是瞬间的
MySQL的SELECT SUM(钱),平均(钱)从t_group其中user_name ='国宝'
+ -------------- + ------------ +
|总和(钱)平均(钱)|
+ -------------- + ------------ +
| 319992383.84 | 246.417910 |
+ ----------------------- - ------------ +
1集行(2.15秒)
其他聚集函数的结果就不是完整的索引扫描了耗时2.15秒。
对于小表的 *** 作
MYSQL>选择分(钱),最大从t_group_david(钱)
+ ------------ + ------------ +
|分(钱)| MAX(钱)|
+ ------------ + ------------ +
| -6.41 | 500.59 |
+ ------- ----- + ------------ +
1集行(1.50秒)
眼霜最小值完全什么全表扫描,耗时1.50秒,不划算。以此看来,
MySQL的>SELECT SUM(钱),AVG(钱)从t_group_david
+ -------------- + ------------ +
|总和(钱)| AVG (钱)|
+ -------------- + ------------ +
| 319992383.84 | 246.417910 |
+ ---- -------- + ------------ +
1行集(1.68秒)
取得这两个结果也是花了快2秒,快了一点。
我们来看看这个小表的结构。
MYSQL>DESC t_group_david
+ ----------- + ------------------ - ----- + ----- + ------ + ---------------- +
|领域| | NULL |键型|中|额外时加入|
+ ------------- + ------------------ + - - + ----- + ------ + ---------------- +
| ID | INT (10)无符号| |优先级| NULL | AUTO_INCREMENT
| | 钱|十进制(10,2)|号| | |
| | USER_NAME | VARCHAR(20)号的MUL | |
| | CREATE_TIME |时间戳| NO | | CURRENT_TIMESTAMP的| |
+ ----------- + ------------------ + ------ + ----- + ------ + ---------------- +
4行集(0.00秒)
明显的user_name的属性是多余的那么就干掉它。
MySQL的>ALTER TABLE t_group_david下降USER_NAME
查询确定,1298576行的影响(7.58秒)
记录:1298576重复:0警告:0
现在来重新对小表运行查询
MYSQL>选择分(钱),最大(钱)从t_group_david
+ ------------ + ------------ +
|分(钱)最大(钱)|
+ ------------ + ------------ +
| -6.41 | 500.59 |
+ ------------ + ------------ +
1行集(0.00秒)
此时是瞬间的。
MYSQL>SELECT SUM(钱),AVG(钱)从t_group_david
+ -------------- + ------------ +
总和(钱)AVG(钱)|
+ -------------- + ------------ +
| 319992383.84 | 246.417910 |
+ - ---------- + ------------ +
1行集(0.94秒)
这次算是控制在一秒以内了。
MySQL的>中止
1.应尽量避免在where子句中对字段进行null值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:selectidfromtwherenumisnullNULL对于大多数数据库都需要特殊处理,mysql也不例外,它需要的代码,的检查和特殊的索引逻辑,有些开发人员完全没有意识到,创建表时NULL是默认值,但大多数时候应该使用NOTNULL,或者使用一个特殊的值,如0,-1作为默认值。不能用null作索引,任何包含null值的列都将不会被包含在索引中。即使索引有多列这样的情况下,只要这些列中有一列含有null,该列就会从索引中排除。也就是说如果某列存在空值,即使对该列建索引也不会提高性能。任何在where子句中使用isnull或isnotnull的语句优化器是不允许使用索引的。此例可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:selectidfromtwherenum=02.应尽量避免在where子句中使用!=或 *** 作符,否则将引擎放弃使用索引而进行全表扫描。MySQL只有对以下 *** 作符才使用索引:,>=,BETWEEN,IN,以及某些时候的LIKE。可以在LIKE *** 作中使用索引的情形是指另一个 *** 作数不是以通配符(%或者_)开头的情形。例如,“SELECTidFROMtWHEREcolLIKE'Mich%'”这个查询将使用索引,但“SELECTidFROMtWHEREcolLIKE'%ike'”这个查询不会使用索引。3.应尽量避免在where子句中使用or来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如:selectidfromtwherenum=10ornum=20可以这样查询:selectidfromtwherenum=10unionallselectidfromtwherenum=204.in和notin也要慎用,否则会导致全表扫描,如:selectidfromtwherenumin(1,2,3)对于连续的数值,能用between就不要用in了:selectidfromtwherenumbetween1and35.下面的查询也将导致全表扫描:selectidfromtwherenamelike'%abc%'或者selectidfromtwherenamelike'%abc'或者若要提高效率,可以考虑全文检索。而selectidfromtwherenamelike'abc%'才用到索引7.如果在where子句中使用参数,也会导致全表扫描。因为SQL只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推迟到运行时;它必须在编译时进行选择。然而,如果在编译时建立访问计划,变量的值还是未知的,因而无法作为索引选择的输入项。如下面语句将进行全表扫描:selectidfromtwherenum=@num可以改为强制查询使用索引:selectidfromtwith(index(索引名))wherenum=@num8.应尽量避免在where子句中对字段进行表达式 *** 作,这将导致引擎放弃使用索引而进行全表扫描。如:selectidfromtwherenum/2=100应改为:selectidfromtwherenum=100*29.应尽量避免在where子句中对字段进行函数 *** 作,这将导致引擎放弃使用索引而进行全表扫描。如:selectidfromtwheresubstring(name,1,3)='abc'--nameselectidfromtwheredatediff(day,createdate,'2005-11-30')=0--‘2005-11-30’生成的id应改为:selectidfromtwherenamelike'abc%'selectidfromtwherecreatedate>='2005-11-30'andcreatedate<'2005-12-1'10.不要在where子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。11.在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致。12.不要写一些没有意义的查询,如需要生成一个空表结构:selectcol1,col2into#tfromtwhere1=0这类代码不会返回任何结果集,但是会消耗系统资源的,应改成这样:createtable#t()13.很多时候用exists代替in是一个好的选择:selectnumfromawherenumin(selectnumfromb)用下面的语句替换:selectnumfromawhereexists(select1frombwherenum=a.num)14.并不是所有索引对查询都有效,SQL是根据表中数据来进行查询优化的,当索引列有大量数据重复时,SQL查询可能不会去利用索引,如一表中有字段sex,male、female几乎各一半,那么即使在sex上建了索引也对查询效率起不了作用。15.索引并不是越多越好,索引固然可以提高相应的select的效率,但同时也降低了insert及update的效率,因为insert或update时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有必要。16.应尽可能的避免更新clustered索引数据列,因为clustered索引数据列的顺序就是表记录的物理存储顺序,一旦该列值改变将导致整个表记录的顺序的调整,会耗费相当大的资源。若应用系统需要频繁更新clustered索引数据列,那么需要考虑是否应将该索引建为clustered索引。17.尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。18.尽可能的使用varchar/nvarchar代替char/nchar,因为首先变长字段存储空间小,可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。19.任何地方都不要使用select*fromt,用具体的字段列表代替“*”,不要返回用不到的任何字段。20.尽量使用表变量来代替临时表。如果表变量包含大量数据,请注意索引非常有限(只有主键索引)。21.避免频繁创建和删除临时表,以减少系统表资源的消耗。22.临时表并不是不可使用,适当地使用它们可以使某些例程更有效,例如,当需要重复引用大型表或常用表中的某个数据集时。但是,对于一次性事件,最好使用导出表。23.在新建临时表时,如果一次性插入数据量很大,那么可以使用selectinto代替createtable,避免造成大量log,以提高速度;如果数据量不大,为了缓和系统表的资源,应先createtable,然后insert。24.如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,先truncatetable,然后droptable,这样可以避免系统表的较长时间锁定。25.尽量避免使用游标,因为游标的效率较差,如果游标 *** 作的数据超过1万行,那么就应该考虑改写。26.使用基于游标的方法或临时表方法之前,应先寻找基于集的解决方案来解决问题,基于集的方法通常更有效。27.与临时表一样,游标并不是不可使用。对小型数据集使用FAST_FORWARD游标通常要优于其他逐行处理方法,尤其是在必须引用几个表才能获得所需的数据时。在结果集中包括“合计”的例程通常要比使用游标执行的速度快。如果开发时间允许,基于游标的方法和基于集的方法都可以尝试一下,看哪一种方法的效果更好。28.在所有的存储过程和触发器的开始处设置SETNOCOUNTON,在结束时设置SETNOCOUNTOFF。无需在执行存储过程和触发器的每个语句后向客户端发送DONE_IN_PROC消息。29.尽量避免大事务 *** 作,提高系统并发能力。30.尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。欢迎分享,转载请注明来源:内存溢出
评论列表(0条)