SQL业务审核与优化
2018-06-17 22:49:33来源:未知 阅读 ()
- 类似与code review
- 评审业务Schema和SQL设计
- 偏重关注性能
- 是业务优化的主要入口之一
- 表和字段命名是否合规
- 字段类型,长度设计是否适当
- 表关联关系是否合理
- 主键,更新时间保留字段等是否符合要求
- 约束,默认值等配置是否恰当
- 了解业务,表数据量,增长模式
- 数据访问模式,均衡度
- 根据业务需求,表是否需要分区,是否有数据什么周期
- SQL语句的执行频率
- 表上是否有合适的索引
- 单次执行的成本
- 执行模式,锁情况分析
- 关注事务上下文
- 业务开发阶段,上线前
- 业务版本变更,线上更新前
-
- 新表和SQL上线
- SQL查询条件变化
- SQL查询频率变化
- 业务逻辑导致现有表数据量规模变化
- SQL审核需要开发与应用运维支持
- 充分沟通,做好必要性说明和教育工作
- 指定业务发布流程,嵌入DBA审核环节
- 积累经验,不断完善评审方法
- 确认应用程序是否向数据库请求了大量超过需要的数据
- 确认mysql服务器层是否在处理大量超过需要的数据记录
- 查询不需要的记录
- 多表关联时返回全部列
- 总是取出全部列
- 重复查询相同的数据
- 响应时间
- 扫描的行数
- 返回的行数
- 使用索引覆盖扫描,把所有需要用的列都放到索引中。
- 改变库表结构。例如使用单独的汇总表
- 重写这个复杂的查询,让mysql优化器能够以更优化的方式执行这个查询。
- 客服端发送一条查询给服务器
- 服务器先检查缓存。如果命中缓存,则立刻返回结果。否则进入下一阶段。
- 服务器端进行SQL解析,预处理,再由优化器生成对应的执行计划。
- mysql根据优化器生成的执行计划,调用存储引擎的API来执行查询。
- 将结果返回给客户端
mysql> show full processlist; +----+------+-----------+--------+---------+------+-------+------------------------+ | Id | User | Host | db | Command | Time | State | Info | +----+------+-----------+--------+---------+------+-------+------------------------+ | 39 | root | localhost | sakila | Sleep | 4 | | NULL | | 40 | root | localhost | sakila | Query | 0 | NULL | show full processlist | +----+------+-----------+--------+---------+------+-------+------------------------+ 2 rows in set (0.00 sec)
mysql> select count(*) from film_actor; +----------+ | count(*) | +----------+ | 5462 | +----------+ 1 row in set (0.00 sec) mysql> show status like 'last_query_cost'; +-----------------+-------------+ | Variable_name | Value | +-----------------+-------------+ | Last_query_cost | 1040.599000 | +-----------------+-------------+
- 统计信息不准确
- 执行计划中的成本估算不等同于实际执行的成本。
-
- 有的计划虽然要读取更多页,但是这些页在缓存中。
- mysql的最有可能和你想的最优不一样。
-
- 比如你希望执行时间尽可能的短,而mysql只是基于成本模型选择的最优执行计划。
- mysql从不考虑其他并发执行的查询,这可能会影响到当前查询速度。
- mysql不会考虑不受其控制的操作的成本。
-
- 如执行存储过程或者用户自定义函数的成本
- 静态优化
-
- 直接对解析树进行分析,并完成优化。优化器通过一些简单的代数变换将where条件转换成另一种等价形式。静态优化在第一次完成后一直有效。可以认为这是一种"编译时优化"
- 动态优化
-
- 动态优化和查询的上下文有关。也和其他很多因素有关,例如where中的取值,索引中条目,等等。每次查询的时候都重新评估,可以认为这是一种"运行时优化"
- 重新定义关联表的顺序。
- 将外联结转成内连接
- 使用等价变化规则
-
- 合并和减少一些比较,移除一些恒成立和一些恒不成立的判断
- 优化count(),min(),max(),min()就直接拿BTree树最左端数据行
- 预估并转换为常数表达式
- 覆盖索引扫描
- 子查询优化
- 提前终止查询
- 等值传播
mysql> select * from film where film_id in ( select film_id from film_actor where actor_id =1) \G;
select * from film where film_id in (1,23,25,106,140);
mysql> explain select * from film f inner join film_actor fa where f.film_id=fa.film_id and actor_id =1; +----+-------------+-------+--------+------------------------+---------+---------+-------------------+------+-------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+--------+------------------------+---------+---------+-------------------+------+-------+ | 1 | SIMPLE | fa | ref | PRIMARY,idx_fk_film_id | PRIMARY | 2 | const | 19 | | | 1 | SIMPLE | f | eq_ref | PRIMARY | PRIMARY | 2 | sakila.fa.film_id | 1 | | +----+-------------+-------+--------+------------------------+---------+---------+-------------------+------+-------+ 2 rows in set (0.00 sec)
(select first_name,last_name from sakila.actor order by last_name) union all (select first_name,last_name from sakila.customer order by last_name) limit 20;
(select first_name,last_name from sakila.actor order by last_name limit 20) union all (select first_name,last_name from sakila.customer order by last_name limit 20) limit 20;
现在中间的临时表中只会包含40条记录。
mysql> explain select min(actor_id) from actor where first_name='PENELOPE'; +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ | 1 | SIMPLE | actor | ALL | NULL | NULL | NULL | NULL | 200 | Using where | +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ 1 row in set (0.00 sec)
mysql> explain select actor_id from actor USE INDEX(PRIMARY) where first_name='PENELOPE' LIMIT 1; +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ | 1 | SIMPLE | actor | ALL | NULL | NULL | NULL | NULL | 200 | Using where | +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ 1 row in set (0.00 sec)
mysql> update tbl AS outer_tbl set cnt = ( select count(*) from tbl AS inner_tbl where inner_tbl.type = outer_tbl.type ); error:you can't specify target table 'outer_tbl' for update in from clause
mysql> update tbl inner join ( select type,count(*) AS cnt from tbl group by type )AS der using(type) set tbl.cnt = der.cnt;
- HIGH_PRIORITY,LOW_PRIORITY
-
- 这个提示告诉mysql,当多个语句同时访问某一个表的时候,哪些语句的优先级相对高些,哪些语句的优先级相对低些。
- 只对使用表锁的存储引擎有效,不要在innodb或者其他有细粒度锁机制和并发控制的引擎中使用。
- DELAYED
-
- 这个提示对insert,replace有效。mysql会将使用该提示的语句立即返回给客户端,并将插入的行数据放入到缓冲区,然后在表空间时批量将数据写入。
- 日志系统使用这样的提示非常有效,或者是其他需要写入大量数据但是客户端却不需要等待单条语句完成I/O的应用。这个用法有一些限制:并不是所有的存储引擎都支持这样的做法;并且该提示会导致函数LAST_INSERT_ID无法正常工作。
- USE INDEX,IGNORE INDEX ,FORCE INDEX
mysql> show status like 'com%'; +---------------------------+-------+ | Variable_name | Value | +---------------------------+-------+ | Com_admin_commands | 0 | | Com_assign_to_keycache | 0 | | Com_alter_db | 0 | | Com_alter_procedure | 0 | | Com_alter_server | 0 | | Com_alter_table | 0 |
- 慢查询日志,定位低效SQL;long_query_time,慢查询的标准时间;
- 慢查询是,查询结束之后才记录;因此他不是实时的;show processlist 查看mysql在进行的线程,查看线程的一些状态,可以实时地查看SQL的执行情况;
mysql> explain select b from t where a =1; +----+-------------+-------+------+---------------+------+---------+-------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+-------+------+-------------+ | 1 | SIMPLE | t | ref | a | a | 5 | const | 1 | Using where | +----+-------------+-------+------+---------------+------+---------+-------+------+-------------+ 1 row in set (0.00 sec)
- select_type
-
- simple:简单表,即不使用表链接或者子查询
- Primary:主查询,即外层的查询
- union:union中的第二个或者后面的查询语句
- subquery: 子查询中的第一个select
- table:输出结果集的表
- type:访问类型
-
- all,全表扫描
- index,索引全扫描
- range,索引范围扫描,常见于< , >,between
- ref,使用非唯一索引扫描或唯一索引的前缀扫描,返回匹配某个单独值的记录行
- eq_ref,类似ref,区别在于使用了唯一索引;
- const/system,表中最多有一个匹配行;Primary key 或 unique index;
- null,不用访问表或者索引就可以得到结果
- possible_keys:表示查询时可能使用的索引
- key: 表示实际使用的索引
- key_len: 使用到索引字段的长度
- rows:扫描行的数量
- extra:执行情况的说明和描述;
mysql> select @@have_profiling; +------------------+ | @@have_profiling | +------------------+ | YES | +------------------+
mysql> select @@profiling; +-------------+ | @@profiling | +-------------+ | 0 | +-------------+ 1 row in set (0.00 sec)
mysql> set profiling=1; Query OK, 0 rows affected (0.00 sec)
mysql> select count(*) from payment; +----------+ | count(*) | +----------+ | 16049 | +----------+ 1 row in set (0.02 sec)
mysql> show profiles; +----------+------------+------------------------------+ | Query_ID | Duration | Query | +----------+------------+------------------------------+ | 1 | 0.01064275 | select count(*) from payment | | 2 | 0.00048225 | show databases | | 3 | 0.00015000 | show DATABASE() | | 4 | 0.00039975 | show tables | +----------+------------+------------------------------+
mysql> show profile for query 4; +----------------------+----------+ | Status | Duration | +----------------------+----------+ | starting | 0.000058 | | checking permissions | 0.000009 | | Opening tables | 0.000050 | | System lock | 0.000008 | | init | 0.000012 | | optimizing | 0.000005 | | statistics | 0.000012 | | preparing | 0.000010 | | executing | 0.000007 | | checking permissions | 0.000132 | | Sending data | 0.000042 | | end | 0.000007 | | query end | 0.000007 | | closing tables | 0.000005 | | removing tmp table | 0.000009 | | closing tables | 0.000006 | | freeing items | 0.000015 | | logging slow query | 0.000005 | | cleaning up | 0.000006 | +----------------------+----------+ 19 rows in set (0.00 sec)
mysql> show profile cpu for query 4; +----------------------+----------+----------+------------+ | Status | Duration | CPU_user | CPU_system | +----------------------+----------+----------+------------+ | starting | 0.000058 | 0.000000 | 0.000000 | | checking permissions | 0.000009 | 0.000000 | 0.000000 | | Opening tables | 0.000050 | 0.000000 | 0.000000 | | System lock | 0.000008 | 0.000000 | 0.000000 | | init | 0.000012 | 0.000000 | 0.000000 | | optimizing | 0.000005 | 0.000000 | 0.000000 | | statistics | 0.000012 | 0.000000 | 0.000000 | | preparing | 0.000010 | 0.000000 | 0.000000 | | executing | 0.000007 | 0.000000 | 0.000000 | | checking permissions | 0.000132 | 0.000000 | 0.000000 | | Sending data | 0.000042 | 0.000000 | 0.000000 | | end | 0.000007 | 0.000000 | 0.000000 | | query end | 0.000007 | 0.000000 | 0.000000 | | closing tables | 0.000005 | 0.000000 | 0.000000 | | removing tmp table | 0.000009 | 0.000000 | 0.000000 | | closing tables | 0.000006 | 0.000000 | 0.000000 | | freeing items | 0.000015 | 0.000000 | 0.000000 | | logging slow query | 0.000005 | 0.000000 | 0.000000 | | cleaning up | 0.000006 | 0.000000 | 0.000000 | +----------------------+----------+----------+------------
- B-Tree 索引:大部分引擎都支持B-Tree索引
- HASH索引:只有memory引擎支持,使用场景简单。
- R-Tree索引:空间索引,Myisam引擎的一个特殊索引类型,主要用于地理空间数据类型
- Full-text:全文索引
mysql> show status like 'Handler_read%'; +-----------------------+-------+ | Variable_name | Value | +-----------------------+-------+ | Handler_read_first | 1 | | Handler_read_key | 6 | | Handler_read_last | 0 | | Handler_read_next | 16050 | | Handler_read_prev | 0 | | Handler_read_rnd | 0 | | Handler_read_rnd_next | 297 | +-----------------------+-------+ 7 rows in set (0.00 sec)
- Handler_read_key :值高,证明索引正在工作;值低,说明增加索引得到的性能改善不高,因为索引不经常使用
- Handler_read_rnd_next:值高,意味着查询效率低,应该建立索引补救;
mysql> analyze table store; +--------------+---------+----------+----------+ | Table | Op | Msg_type | Msg_text | +--------------+---------+----------+----------+ | sakila.store | analyze | status | OK | +--------------+---------+----------+----------+ 1 row in set (0.00 sec)
mysql> check table store; +--------------+-------+----------+----------+ | Table | Op | Msg_type | Msg_text | +--------------+-------+----------+----------+ | sakila.store | check | status | OK | +--------------+-------+----------+----------+ 1 row in set (0.01 sec)
mysql> optimize table store; +--------------+----------+----------+-------------------------------------------------------------------+ | Table | Op | Msg_type | Msg_text | +--------------+----------+----------+-------------------------------------------------------------------+ | sakila.store | optimize | note | Table does not support optimize, doing recreate + analyze instead | | sakila.store | optimize | status | OK | +--------------+----------+----------+-------------------------------------------------------------------+ 2 rows in set (0.04 sec)
mysql> alter table payment engine=innodb; Query OK, 16049 rows affected (0.62 sec) Records: 16049 Duplicates: 0 Warnings: 0
- alter table tbl_name disable keys;
- load data infile '/home/mysql/film_test3.txt' into table film_test4;
- alter table tbl_name enable keys;
- 因为innodb的表是按照主键的顺序保存的,索引将导入的数据按照主键的顺序排序,可以有效地提高导入数据的效率;
- 在导入数据前执行 set unique_checks=0 ,关闭唯一性校验,在导入结束后执行 set unique_checks=1,恢复唯一性校验;
- 如果应用使用自动提交的方式,建议在导入前执行:set autocommit=0,关闭自动提交,在导入完成之后,再开启;
- 使用多个值表的insert比单个insert语句快,因为多值表一起插入,缩减了客户端与数据库之间的连接,关闭等消耗;
-
- insert into test values(1,2),(2,3),(3,4).....
- 将索引文件和数据文件分在不同的磁盘上存放(利用建表中的选项)
- 当从一个文本装载一个表时,使用load data infile ,这通常比使用很多insert 语句快20倍;
- 如果从不同客户插入很多行,insert delayed 语句得到更高的速度;将数据都放入内存中,然后合并一起insert,减少客户端与数据库的交互
- 第一种通过有序索引顺序扫描直接返回有序数据,这种方式在使用explain 分析查询的时候显示为useing index,不需要额外的排序,操作效率较高。
- 第二种是通过返回数据进行排序,也就是filesort排序,所有不是通过索引直接返回排序结果的排序都叫filesort排序。
mysql> alter table customer add index idx_email_storeid (email,store_id); Query OK, 0 rows affected (0.04 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> explain select store_id,email, customer_id from customer order by email\G; *************************** 1. row *************************** id: 1 select_type: SIMPLE table: customer type: index possible_keys: NULL key: idx_email_storeid key_len: 154 ref: NULL rows: 652 Extra: Using index 1 row in set (0.00 sec)
mysql> alter table customer drop index idx_email_storeid; Query OK, 0 rows affected (0.01 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> alter table customer add index idx_storeid_email (store_id,email); Query OK, 0 rows affected (0.03 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> explain select store_id,email, customer_id from customer order by email\G; *************************** 1. row *************************** id: 1 select_type: SIMPLE table: customer type: index possible_keys: NULL key: idx_storeid_email key_len: 154 ref: NULL rows: 652 Extra: Using index; Using filesort 1 row in set (0.00 sec)
- select * from tabname order by key_part1,key_part2,......;
- select * from tabname where key_part1=1 order by key_part1 DESC, key_part2 DESC;
- select * from tabname order by key_part1 DESC, key_part2 DESC;
- select * from tabname order by key_part1 desc ,key_part2 asc;
-
- order by 的字段混合 ASC,DESC
- select * from tabname where key2 = 2 order by key1;
-
- 用于查询行的关键字与order by 中使用的不相同
- select * from tabname order by key1,key2;
- 两次扫描算法:首先根据条件取出排序字段和行指针信息,之后在排序区sort buffer中排序。优点是排序的时候内存开销较小,但排序效率低;
- 一次扫描算法:一次性去除满足条件的行的所有字段,然后在排序区sort buffer中排序后直接输出结果。优点排序效率比两次扫描高,但内存开销大;
mysql> explain select payment_date,sum(amount) from payment group by payment_date \G; *************************** 1. row *************************** id: 1 select_type: SIMPLE table: payment type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 16451 Extra: Using temporary; Using filesort 1 row in set (0.01 sec)
使用order by null优化group by
mysql> explain select payment_date,sum(amount) from payment group by payment_date ORDER BY NULL \G; *************************** 1. row *************************** id: 1 select_type: SIMPLE table: payment type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 16451 Extra: Using temporary 1 row in set (0.00 sec)
mysql> explain select film_id,description from film order by title limit 50,5; +----+-------------+-------+------+---------------+------+---------+------+------+----------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+------+------+----------------+ | 1 | SIMPLE | film | ALL | NULL | NULL | NULL | NULL | 1134 | Using filesort | +----+-------------+-------+------+---------------+------+---------+------+------+----------------+ 1 row in set (0.00 sec)
mysql> explain select film_id,description from film inner join ( select film_id from film order by title limit 50,5) AS lim using(film_id); +----+-------------+------------+--------+---------------+-----------+---------+-------------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+------------+--------+---------------+-----------+---------+-------------+------+-------------+ | 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 5 | | | 1 | PRIMARY | film | eq_ref | PRIMARY | PRIMARY | 2 | lim.film_id | 1 | | | 2 | DERIVED | film | index | NULL | idx_title | 767 | NULL | 55 | Using index | +----+-------------+------------+--------+---------------+-----------+---------+-------------+------+-------------+ 3 rows in set (0.00 sec)
mysql> select * from rental order by rental_id limit 5; +-----------+---------------------+--------------+-------------+---------------------+----------+---------------------+ | rental_id | rental_date | inventory_id | customer_id | return_date | staff_id | last_update | +-----------+---------------------+--------------+-------------+---------------------+----------+---------------------+ | 1 | 2005-05-24 22:53:30 | 367 | 130 | 2005-05-26 22:04:30 | 1 | 2006-02-15 21:30:53 | | 2 | 2005-05-24 22:54:33 | 1525 | 459 | 2005-05-28 19:40:33 | 1 | 2006-02-15 21:30:53 | | 3 | 2005-05-24 23:03:39 | 1711 | 408 | 2005-06-01 22:12:39 | 1 | 2006-02-15 21:30:53 | | 4 | 2005-05-24 23:04:41 | 2452 | 333 | 2005-06-03 01:43:41 | 2 | 2006-02-15 21:30:53 | | 5 | 2005-05-24 23:05:21 | 2079 | 222 | 2005-06-02 04:33:21 | 1 | 2006-02-15 21:30:53 | +-----------+---------------------+--------------+-------------+---------------------+----------+---------------------+
mysql> select * from rental where rental_id > 5 order by rental_id limit 5; +-----------+---------------------+--------------+-------------+---------------------+----------+---------------------+ | rental_id | rental_date | inventory_id | customer_id | return_date | staff_id | last_update | +-----------+---------------------+--------------+-------------+---------------------+----------+---------------------+ | 6 | 2005-05-24 23:08:07 | 2792 | 549 | 2005-05-27 01:32:07 | 1 | 2006-02-15 21:30:53 | | 7 | 2005-05-24 23:11:53 | 3995 | 269 | 2005-05-29 20:34:53 | 2 | 2006-02-15 21:30:53 | | 8 | 2005-05-24 23:31:46 | 2346 | 239 | 2005-05-27 23:33:46 | 2 | 2006-02-15 21:30:53 | | 9 | 2005-05-25 00:00:40 | 2580 | 126 | 2005-05-28 00:22:40 | 1 | 2006-02-15 21:30:53 | | 10 | 2005-05-25 00:02:21 | 1824 | 399 | 2005-05-31 22:44:21 | 2 | 2006-02-15 21:30:53 | +-----------+---------------------+--------------+-------------+---------------------+----------+---------------------+ 5 rows in set (0.00 sec)
- mysql客户端和服务器间:半双工
- show processlist,实时查看SQL执行情况;
- 查询优化器:
-
- 统计信息:
-
- 每个表/索引的页面个数,
- 索引的基数,索引和数据行的长度,索引分布情况;
- 不考虑任何缓存假设数据读取需要一次IO;
- 优化策略:
-
- 静态优化,“编译时优化”
- 动态优化“运行时优化”
- 查询优化器的局限:
-
- 关联子查询,使用连接替代(5.6之后优化器已经自动优化了);
- union限制,需每个子句都limit 20控制临时表数量;
- 最大值和最小值优化,不能自动更据主键ID 选择;
- 不允许在同一表上更新和查询,可以使用内连接跳过限制;
- hint:
-
- use index
- ignore index
- force index
- 慢查询分析:
-
- show status like 'com%':
-
- 了解读写比例;
- 事务回滚比例;
- 视图连接mysql服务器的次数;
- 慢查询的次数;
- 定位低效SQL:慢查询日志
- explain分析低效SQL:
-
- explain extended 可以得到更清晰易读的SQL,多出来warning;
- explain partition 找到select到底是在哪个分区查询;
- show profile 分析SQL:
-
- show profile 能够在做SQL优化时帮助我们了解时间都耗费到哪里去了;
- 通过show profiles 找出query id,
- 通过show profile for query id 分析具体的SQL;能够看到执行过程中线程的每个状态和消耗的时间;也能根据cpu,io,等具体参数;
- trace:5.6之后可以使用,通过trace文件能够进一步了解为什么优化器选择A执行计划而不选择B执行计划,帮助我们更好地理解优化器的行为
- 索引使用情况:
-
- show status like 'Handler_read%'
- Handler_read_key:值高,证明索引正在工作;值低,说明增加索引得到的性能改善不高,因为索引不经常使用;
- Handler_read_rnd_next:值高,意味着查询效率低,应该建立索引补救;
- 定期分析表和检查表:使系统得到准确的统计信息,使优化器更好工作;
- 常用SQL优化:
-
- load:
-
- myisam,导入前,使索引失效,导入后,开启索引;
- innodb,关闭唯一性校验
- insert:多值表插入,
- order by:
-
- 索引排序:
-
- where条件和order by使用相同索引
- order by 的顺序和索引顺序相同
- order by 字段都是升序或降序,
- filesort:两次扫描算法,一次扫描算法;
- group by:group by 默认对字段排序,使用order by null 来禁止排序;
- 子查询可以使用连接代替
- or条件使用索引需要左右都要有索引段;
- 分页查询
-
- “延迟关联”,
- “首先获得第一组,然后使用书签方式”
- 将大查询分解为多个小查询
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
上一篇:mysql字符集
- MySQL replace函数怎么替换字符串语句 2020-03-09
- PHP访问MySQL查询超时怎么办 2020-03-09
- mysql登录时闪退 2020-02-27
- MySQL出现1067错误号 2020-02-27
- mysql7.x如何单独安装mysql 2020-02-27
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash