`

mysql 的innodb和myisam数据库引擎的认识

阅读更多

mysql数据库新加了几个表,结果只有frm文件存在,如果直接复制到别的电脑,这几个表是提示错误的,为什么呢?查了下资料:frm、MYI、MYD分别对应MyISAM表的表结构\索引\数据文件。

我遇到的情况跟表引擎类型有关,我是用innodb,结果出现了这样的情形,MYSQL的默认DB引擎是innodb的时候,innodb表没有没有myd和.myi,其数据文件对应于ibdata1

解决办法,更改表引擎为MYISAM:

最好确认下是否是innodb引擎
进入你的mysql数据库(不管你是用phpmyadmin还是mysql命令行)
mysql> use 数据库名
mysql>show tables;
mysql>show table status like '数据库表名'
如果type=innodb的话
你就可以转换表引擎了

mysql>ALTER TABLE 数据库表名 ENGINE=MYISAM 或 alter table 数据库表名 type='MYISAM'

这样就可以修改一个表的引擎
如果你的数据库中的表引擎本来就是myisam了,那你需要确认下你的数据目录到底在哪里
mysql>show variables like 'datadir%';

也可以使用phpmyadmin,选中表,操作,表选项,Storage Engine改成MYISAM 执行 就ok了

 

MySQL导入innodb引擎的 frm文件  直接复制对应的数据库文件夹是不行的,在新的数据库里会提示没有相关表数据

因为innodb的存储格式是这样存储的: 数据库文件夹里只有.frm格式的文件,这样的文件是存储的数据库表的结构,

没有数据,数据统一存在ibdata1文件里,所以用复制的方法备份或是移动数据库时要注意也要将data下的ibdata1文件一起复制过去,

如果用 mysqldump -h mysql服务名 -u 用户名 -p > sql.sql 来备份的话就没这个问题

 


innodb 类型的数据 是不管你有多少个子数据库, 数据全部写入 ibdata1这一个文件,造成数据库大了以后 如果你的硬件配置不是很好的话执行速度极慢,

myisam 是分开存储,比如你论坛数据库是 bbs 那么论坛数据表就全部储存在mysql/data/bbs 下,其他数据库就保存在其他数据文件夹下。


如果是小表,用myisam比innodbk快,但快的也不明显,毫秒级的。如果是大表,上千万条记录了,那你赶快放弃myisam吧,innodb比它快的太明显了。

如果画条性能曲线,在数据量增长的过程中,myisam的曲线下降的非常快,而innodb就比较平稳.

再者就是myisam不支持事务处理等高级处理! 你用phpmyadmin优化下数据库数据库也会减少


/*
MYSQL的事务处理主要有两种方法。
1、用begin,rollback,commit来实现
begin 开始一个事务
rollback 事务回滚
commit 事务确认
2、直接用set来改变mysql的自动提交模式
MYSQL默认是自动提交的,也就是你提交一个QUERY,它就直接执行!我们可以通过
set autocommit=0 禁止自动提交
set autocommit=1 开启自动提交
来实现事务的处理。
当你用 set autocommit=0 的时候,你以后所有的SQL都将做为事务处理,直到你用commit确认或rollback结束。
注意当你结束这个事务的同时也开启了个新的事务!按第一种方法只将当前的作为一个事务!
个人推荐使用第一种方法!

MYSQL中只有INNODB和BDB类型的数据表才能支持事务处理!其他的类型是不支持的!

***:一般MYSQL数据库默认的引擎是MyISAM,这种引擎不支持事务!如果要让MYSQL支持事务,可以自己手动修改:

方法如下:1.修改c:\appserv\mysql\my.ini文件,找到skip-InnoDB,在前面加上#,后保存文件。
2.重启mysql服务。
3.mysql->show engines;(或执行mysql->show variables like 'have_%'; ),查看have_InnoDB为YES,即表示数据库支持InnoDB了。
也就说明支持事务transaction了。

4.在创建表时,就可以为Storage Engine选择InnoDB引擎了。如果是以前创建的表,
可以使用mysql->alter table table_name type=InnoDB;或 mysql->alter table table_name engine=InnoDB;
来改变数据表的引擎以支持事务。
*/

 

Mysql 事务简介

什么是事务?
通俗点来说, 事务就是对一组由N条SQL语句(N>=1)组成的逻辑处理单元进行并发控制.

当这组SQL语句都执行成功时才会对数据库构成实际影响. 否则只要有一条SQL语句执行失败,

那么整组SQL都不会执行成功, 都不会对数据库有实际影响. 这样能确保这个事务中的这组SQL操作的统一性, 保证数据一致性.

我们来结合实际的例子来理解事务的概念:

执行下面的操作 

1, 建立不支持事务的数据表 tbl_a 

CREATE TABLE IF NOT EXISTS `tbl_a` ( 

   `id` int(11) NOT NULL AUTO_INCREMENT, 

   `val` varchar(100) NOT NULL, 

   PRIMARY KEY (`id`) 

 ) ENGINE=MyISAM AUTO_INCREMENT=1 ; 

   

2, 为 tbl_a 插入数据, 将下面 4 条语句全部复制, 用 phpMyAdmin 一并执行 

INSERT INTO tbl_a (val) VALUES ('a'); 

INSERT INTO tbl_a (val) VALUES ('b'); 

INSERT INTO tbl_a (vals) VALUES ('c'); -- 因为表中没有 vals 这个字段, 执行到这句时会报错. 

INSERT INTO tbl_a (val) VALUES ('d');  -- 因为程序已经中断, 这句不执行 

  

3, 我们来看看 tbl_a 中的数据, 会发现有两条数据. 

SELECT * FROM tbl_a; 

--   +----+-----+ 

--   | id | val | 

--   +----+-----+ 

--   |  1 | a   | 

--   |  2 | b   | 

--   +----+-----+ 

--   很好理解: 因为我们四条语句一并提交, mysql 还是会一条一条的执行: 

--   执行第一句, 没有ERROR, 对数据库产生实际影响, 将 'a' 真真实实的插入到 tbl_a 中 

--   执行第二句, 没有ERROR, 对数据库产生实际影响, 将 'b' 真真实实的插入到 tbl_a 中 

--   执行第三句, 因为没有指定的字段, 抛出ERROR, 程序中断执行.

 

接下来我们再看看事务是怎么处理的:


执行下面的操作 

建立支持事务的数据表 `tbl_b` 

CREATE TABLE IF NOT EXISTS `tbl_b` ( 

   `id` int(11) NOT NULL AUTO_INCREMENT, 

   `val` varchar(100) NOT NULL, 

   PRIMARY KEY (`id`) 

 ) ENGINE=InnoDB AUTO_INCREMENT=1 ; 

   

 -- 2, 为 tbl_b 插入数据

 begin; -- 开启一个事务 

 INSERT INTO tbl_b (val) VALUES ('a'); 

 INSERT INTO tbl_b (val) VALUES ('b'); 

 INSERT INTO tbl_b (vals) VALUES ('c'); -- 报错 

 INSERT INTO tbl_b (val) VALUES ('d'); 

 commit; 

   

3, 我们来看看 tbl_b 中的数据, 会和 tbl_a 中的数据有什么差别呢? 

 SELECT * FROM tbl_b; 

 --   Empty set (0.00 sec) 

 --   一条数据也没有, 哈. 这就是事务与非事务的区别, 

 --   因为在事务中遇到了一个错误, 所整个事务中的 SQL 语句都不会对数据库构成实际影响

OK. 现在对事务有了形像的认识之后我们再来结合其它的例子进一步学习事务:

 

 -- 1, 清空 tbl_b 记录 

 TRUNCATE TABLE `tbl_b` 

  

 -- 2, 为 tbl_b 插入数据, 将下面 4 条语句全部复制, 用 phpMyAdmin 一并执行 

 -- begin; -- 注意没有执行 begin 

 INSERT INTO tbl_b (val) VALUES ('a'); 

 INSERT INTO tbl_b (val) VALUES ('b'); 

 INSERT INTO tbl_b (vals) VALUES ('c'); -- 报错 

 INSERT INTO tbl_b (val) VALUES ('d'); 

 -- commit; 

   

 -- 3, 我们来看看 tbl_b 中的数据, 会和有执行 begin 的效果有什么差别? 

 SELECT * FROM tbl_b; 

 --   +----+-----+ 

 --   | id | val | 

 --   +----+-----+ 

 --   |  1 | a   | 

 --   |  2 | b   | 

 --   +----+-----+ 

 --   有两条数据, 这是为什么? 

 --   因为事务数据表中的事务默认是自动提交的(AUTOCOMMIT), 它的执行过程是: 

 --   开启一个事务, 执行第一句, 没有ERROR, 提交事务, 对数据库产生实际影响, 将'a'真真实实的插入到 tbl_b 中 

 --   开启一个事务, 执行第二句, 没有ERROR, 提交事务, 对数据库产生实际影响, 将'b'真真实实的插入到 tbl_b 中 

 --   开启一个事务, 执行第三句, 因为没有指定的字段, 抛出ERROR, 程序中断执行. 

 --   这样明白了为什么要使用 begin 了吧, 换句话说,如果事务表中没有 begin,那它和非事务表执行的效果是一样的

下面是一个成功的例子:


 -- 1, 清空 tbl_b 记录 

 TRUNCATE TABLE `tbl_b`; 

   

 -- 2, 为 tbl_b 插入数据, 将下面 4 条语句全部复制, 用 phpMyAdmin 一并执行 

 begin; 

 INSERT INTO tbl_b (val) VALUES ('a'); 

 INSERT INTO tbl_b (val) VALUES ('b'); 

 INSERT INTO tbl_b (val) VALUES ('c'); 

 INSERT INTO tbl_b (val) VALUES ('d'); 

 -- rollback; -- roolback 可以理解为 un-commit, 不提交 

 commit; -- 注意最后要有 conmmit; 如果这有这一句会怎样? 动手试试吧. 

   

 -- 3, 我们来看看 tbl_b 中的数据, 四条数据成功插入. 

 SELECT * FROM tbl_b;

总结一下:
1, 在 Mysql 中要让数据表支持事务, 必须使用 InnoDB 或 BDB 数据引擎.
2, 事务数据表默认是 autocommit 的, 要开启一个事务应该使用 begin; 或者使用 SET AUTOCOMMIT={1|0} 来设置是否自动提交
3, 事务一定要 commit , 否则没有任何效果

 

相关网络测试:

 
环境:win32,mysql5.0.18,php5.2.3,数据库编码:gbk;
测试程序类似如下:
CODE:

<?php
set_time_limit(0);
function getmicrotime(){
    list($usec, $sec) = explode(" ",microtime());
    return ((float)$usec + (float)$sec);
    }
$link = mysql_connect('localhost','root','');
mysql_select_db('v2l');
mysql_query('set names gbk');


$time_start = getmicrotime();
for ($i=0;$i<100;$i++)
$result = mysql_query("insert into user(groupid,username,pass) values(3,'dafdsfff','dfasfsdfsdf')");
$time_end = getmicrotime();
echo  $time_end - $time_start.'<br>';

?>
user表结构:
CODE:

CREATE TABLE `user` (                                        
          `id` int(10) NOT NULL auto_increment,                      
          `groupid` int(10) NOT NULL,                                
          `username` varchar(50) NOT NULL default '',                
          `pass` varchar(50) NOT NULL default '',                    
          `capital` int(10) NOT NULL default '0' COMMENT '资产',   
          `credits` int(10) NOT NULL default '0',                    
          `address` varchar(200) NOT NULL default '0',               
          `email` varchar(50) NOT NULL default '0',                  
          `phone` varchar(20) NOT NULL default '0',                  
          `post` int(6) NOT NULL default '0',                        
          `num` int(10) NOT NULL default '0' COMMENT '消费次数', 
          `time` int(15) NOT NULL default '0',                       
          PRIMARY KEY  (`id`)                                        
        ) ENGINE=MyISAM DEFAULT CHARSET=gbk ROW_FORMAT=DYNAMIC       
有5557行数据;

测试select:
1:循环1000次,username字段有索引:
查询语句:select * from user where username = 'wwd',估计在3000行左右,只有一条记录
innodb:维持在0.255799055099秒左右;
myisam:维持在0.252280950546秒左右;

2:循环100次,username字段没有索引:
查询语句同上;
innodb:维持在0.793882846832秒左右;
myisam:维持在0.417747974396秒左右;

得出的结论是:无索引时innodb表比myisam慢89%,有基于索引的查询速度差不多。


测试insert:
1:循环100次,username字段有索引:
innodb:维持在2.79042601585秒左右;
myisam:维持在0.0191547870636秒左右;

2:循环100次,username字段没有索引:
innodb:维持在1.58328294754秒左右;
myisam:维持在0.0159208774567秒左右;

得出的结论是:
1:innodb有索引时插入比没有索引时慢77%,myisam有索引时插入比没有索引时慢20%;
2:有索引时innodb比myisam慢146倍,无索引时innodb比myisam慢99倍;

测试update:
1:更新1400条记录,username字段有索引:
更新语句类似:update user set username='aaaaaaaaaafdasfs' where username = 'dafdsfff';此条语句更新1400条记录
innodb:维持在0.167110919952秒左右;
myisam:维持在0.0893239974976秒左右;

2:更新1400条记录,username字段没有索引:
更新语句类似上面;
innodb:维持在0.133745908737秒左右;
myisam:维持在0.0571432113647秒左右;

得出的结论是:
1:innodb有索引时更新比没有索引时慢25%,myisam有索引时更新比没有索引时慢56%;
2:有索引时innodb比myisam慢87%,无索引时innodb比myisam慢135%;


测试delete:
删除100条记录,基于主键id的删除:
删除语句:delete from user where id >5588;
innodb:维持在0.0407979488373秒左右;
myisam:维持在0.0035240650177秒左右;

得出的结论是:
基于主键时删除innodb比myisam慢11倍;
fleaphp (2007-8-01 11:47:50)操作 innodb 表前打开事务,操作完成后再提交事务,性能会有很大不同哦,呵呵
adslcat (2007-8-01 12:05:21)又是一个比较马和鱼哪个跑的快的月经帖.
wwd (2007-8-01 12:12:28)QUOTE:

原帖由 fleaphp 于 2007-8-1 11:47 发表
操作 innodb 表前打开事务,操作完成后再提交事务,性能会有很大不同哦,呵呵
这个好像没用。我的代码是这么写的:
[php]for ($i=0;$i<100;$i++)
{
        mysql_query("start transaction");
        $result = mysql_query("insert into user(groupid,username,pass) values(3,'dafdsfff','dfasfsdfsdf')");
        mysql_query("commit");
}[/php]

把innodb_flush_log_at_trx_commit设置成0或者2都会提升性能,但是在崩溃恢复是会损失最后一秒的事务。
神仙 (2007-8-01 13:42:38)mysql_query("start transaction");
for ($i=0;$i<100;$i++)
{
        $result = mysql_query("insert into user(groupid,username,pass) values(3,'dafdsfff','dfasfsdfsdf')");
}
mysql_query("commit");
你放循环里面和不加那两行代码没啥区别的

还有,你没有测试在高并发读写时的性能。这才是innodb的长处。
Snake.Zero (2007-8-01 16:53:11)QUOTE:

原帖由 fleaphp 于 2007-8-1 11:47 发表
操作 innodb 表前打开事务,操作完成后再提交事务,性能会有很大不同哦,呵呵
选择innoDb的理由和myISAM是肯定不同的,什么时候用什么类型是根据需求决定的,这种比较是完全没有意义的
怪物史莱克 (2007-8-01 17:14:08)QUOTE:

原帖由 Snake.Zero 于 2007-8-1 16:53 发表


选择innoDb的理由和myISAM是肯定不同的,什么时候用什么类型是根据需求决定的,这种比较是完全没有意义的
yeah
存在就一定有他存在的道理。
wwd (2007-8-01 19:27:06)QUOTE:

原帖由 神仙 于 2007-8-1 13:42 发表
mysql_query("start transaction");
for ($i=0;$i
嗯,我在手册里也看到了,想研究一下高并发下面测试mysql性能。
结果发现用apache的ab测试的话,高于1000个并发就不行了,导致系统死机;
用smacks测试的话,并发高于200的就不行了,会出现插入失败,低于200的话插入正常;
请问有没有好的办法?
nightsailer (2007-8-02 00:04:45)Innodb和MyISAM纯比较速度就是比性能了?太片面了吧。
二者的特点和适用情况都有很多的成熟的方案和讨论,搜一下就知道不用这样去测,
得出的数据也是片面的不能作为决策的依据的。
建议你去
http://www.mysqlperformanceblog.com/
看看


http://www.mysqlperformanceblog.com/2007/01/08/innodb-vs-myisam-vs-falcon-benchmarks-part-1/

作为参考

[ 本帖最后由 nightsailer 于 2007-8-2 00:15 编辑 ]
Snake.Zero (2007-8-02 07:53:29)QUOTE:

原帖由 wwd 于 2007-8-1 19:27 发表

嗯,我在手册里也看到了,想研究一下高并发下面测试mysql性能。
结果发现用apache的ab测试的话,高于1000个并发就不行了,导致系统死机;
用smacks测试的话,并发高于200的就不行了,会出现插入失败,低于2 ...
MYSQL是有瓶颈的,一般的应用不可能在写入的时候达到200,算算看一瞬间能有200次插入的网站,那已经不是程序所需要考虑的事情了,已经涉及到硬件了
wwd (2007-8-02 10:17:31)QUOTE:

原帖由 Snake.Zero 于 2007-8-1 16:53 发表


选择innoDb的理由和myISAM是肯定不同的,什么时候用什么类型是根据需求决定的,这种比较是完全没有意义的
^_^,我有的时候不知道用什么表,因为同样的需求有不同的解决方法。我举个例子吧。比方说批量删除文章。我有两个思路:
第一个(使用事务):
         1:先根据条件查出要删除文章的总数;
         2:根据条件删除文章并得到受影响的行数;
         3:比较上述两条得到的数目,如果相等则commit,否则rollback;
第二个(不使用事务):
        根据条件直接删除文章;

我觉得第一个思路更安全一些,不过它使用事务,而且查询比较多,用innodb表,而第二个思路用myisam就可以,查询也相对少一些。但通常我看到的源代码程序都是使用第二个思路,请问你觉得应该用哪个?

[ 本帖最后由 wwd 于 2007-8-2 10:19 编辑 ]
wwd (2007-8-02 10:22:47)QUOTE:

原帖由 nightsailer 于 2007-8-2 00:04 发表
Innodb和MyISAM纯比较速度就是比性能了?太片面了吧。
二者的特点和适用情况都有很多的成熟的方案和讨论,搜一下就知道不用这样去测,
得出的数据也是片面的不能作为决策的依据的。
建议你去
http://www.my...
完全同意你所说的道理,不过我就是想测试一下他们之间的速度差别。
如果是某一个场合必须用innodb,那不管他速度如何我都会用;
但是如果一个场合可以用innodb,也可以用myisam,那我就想测试下他们之间的速度差别,以此来决定到底用哪个。

分享到:
评论

相关推荐

    MyISAM引擎与InnoDB引擎性能的对比

    MySQL数据库系统提供了多种存储引擎,其中最常用的两种是MyISAM和InnoDB。它们各自具有独特的特性和适用场景,理解二者的性能差异对于优化数据库设计至关重要。 MyISAM引擎是MySQL早期的默认存储引擎,以其高速度和...

    mysql更改引擎(InnoDB,MyISAM)的方法

    mysql默认的数据库引擎是MyISAM,不支持事务和外键,也可使用支持事务和外键的InnoDB。 查看当前数据库的所支持的数据库引擎以及默认数据库引擎 数据库支持的引擎和默认数据库引擎代码: 代码如下:show engines; ...

    《MYSQL备份与恢复》之 Innodb与 MyISAM引擎

    《MYSQL备份与恢复》之 Innodb与 MyISAM引擎 一、系统环境 1.1 ubuntu 12.0.4 X86_64 1.2 percona-xtrabackup-2.0.3.tar.gz 1.3 xtrabackup简介 xtrabackup是一个对InnoDB做数据备份的工具,支持在线热备份(备份时...

    mysql DB引擎myisam与innodB

    在 MySQL 数据库系统中,存在多种不同的存储引擎,其中最为人所熟知且广泛使用的两种是 MyISAM 和 InnoDB。这两种存储引擎各自具有独特的特点和适用场景。 #### InnoDB:事务安全与外键支持 InnoDB 是 MySQL 中...

    MySQL内核:InnoDB存储引擎 卷1.pdf.zip

    InnoDB作为MySQL中最常用且最重要的存储引擎,负责处理事务处理、数据完整性以及并发控制等关键任务,因此对它的深入理解对于数据库管理员和开发者至关重要。 InnoDB存储引擎是MySQL中的默认存储引擎,特别适合需要...

    MySQL存储引擎之争-InnoDB与MyISAM全面对决

    综合来看,尽管InnoDB在事务和并发控制方面表现更优,已成为MySQL的默认存储引擎,但MyISAM在读密集型应用和空间敏感应用中仍有一定的优势。在选择存储引擎时,应根据实际应用的需求,如事务处理的重要性、并发用户...

    MySQL数据库MyISAM存储引擎转为Innodb的方法.doc

    MySQL数据库MyISAM存储引擎转为Innodb的方法.doc

    MySQL InnoDB和MyISAM数据引擎的差别分析

    MySQL中的InnoDB和MyISAM是两种非常重要的存储引擎,它们各自有着独特的特性和适用场景。在选择使用哪种引擎时,需要根据实际的应用需求来决定。 InnoDB是MySQL的默认存储引擎,它提供了ACID(原子性、一致性、隔离...

    8.MySQL存储引擎--MyISAM与InnoDB区别1

    MyISAM和InnoDB是MySQL中最常用的两种存储引擎,它们都有其优缺点,本文将对比MyISAM和InnoDB存储引擎的区别。 FULLTEXT索引 MyISAM支持FULLTEXT索引,而InnoDB不支持。FULLTEXT索引可以对文本字段进行索引,以提高...

    mysql架构与存储引擎(MySQL逻辑架构、InnoDB引擎、MyISAM引擎、存储引擎选择).docx

    除了InnoDB和MyISAM之外,MySQL还支持多种其他的存储引擎,如Memory、Archive、Federated等,这些引擎各有特色,可以满足不同的业务需求。 #### 四、存储引擎选择 选择合适的存储引擎对于保证数据库性能和稳定性至...

    MySQL数据库引擎快速指导

    InnoDB和BDB引擎则为MySQL带来了事务处理和外键支持,这是ISAM和MyISAM所欠缺的。InnoDB是较为流行的事务型引擎,虽然相对较慢,但对于需要ACID(原子性、一致性、隔离性、持久性)特性的应用至关重要。BDB...

    Innodb与Myisam引擎的区别与应用场景

    在MySQL数据库管理系统中,选择合适的存储引擎对于确保数据的安全性、完整性和性能至关重要。其中,InnoDB和MyISAM是最为常见的两种存储引擎,它们各自具备独特的特性和适用场景。下面将详细探讨这两种引擎的主要...

    mysql 中InnoDB和MyISAM的区别分析小结

    MySQL中的InnoDB和MyISAM是两种非常常见的存储引擎,它们各自有着独特的特性和适用场景。下面我们将深入探讨这两种引擎的主要区别。 1. **索引支持**: - MyISAM支持全文索引(FULLTEXT),这对于需要进行全文搜索...

    MySQL存储引擎MyISAM与InnoDB区别总结整理

    MyISAM存储引擎的特点是:表级锁、不支持事务和全文索引,适合一些CMS内容管理系统作为后台数据库使用,但是使用大并发、重负荷生产系统上,表锁结构的特性就显得力不从心; 以下是MySQL 5.7 MyISAM存储引擎的版本...

    MyISAM和InnoDB的异同

    MyISAM和InnoDB是MySQL中最常用的两种存储引擎,它们各自拥有不同的特点和适用场景。 #### MyISAM引擎概述 MyISAM是MySQL早期默认使用的存储引擎,它主要适用于读取密集型的应用场景。MyISAM支持表级锁定,这意味...

    MySQL数据库INNODB 表损坏修复处理过程

    MySQL报警,从库的数据库挂了,一直在不停的重启,打开错误日志,发现有张表坏了。innodb表损坏不能通过repair table 等修复myisam的命令操作。

    MySQL数据库:MySQL存储引擎.pptx

    数据库和表的创建和管理;;存储引擎就是如何存储数据、如何为存储的数据建立索引和如何更新、查询数据等技术的实现方法。因为在关系数据库中数据的存储是以表的形式存储的,所以存储引擎简而言之就是指表的类型。...

    Mysql数据库引擎大揭秘

    目前,MySQL 提供多种数据库引擎,如InnoDB、MyISAM和Memory,以适应不同应用场景。 1.3 数据库引擎分类和特点 - 关系型数据库引擎:如MySQL,使用表格结构,支持SQL,强调数据一致性,适用于结构化数据存储。 - 非...

Global site tag (gtag.js) - Google Analytics