Mysql 优化大型数据集表的适当索引(或删除)

Mysql 优化大型数据集表的适当索引(或删除),mysql,sql,optimization,query-optimization,Mysql,Sql,Optimization,Query Optimization,我们有一个“访问者”跟踪模式正在运行——当推送时,它似乎会对DB服务器造成一些压力 VISITORS表通过哈希current records 310000标识唯一用户。对散列执行搜索,如果未找到,则添加该散列。以下两个表需要ID CREATE TABLE visitors ( id int(10) UNSIGNED NOT NULL auto_increment, ip varchar(25) NOT NULL, hash varchar(64) NOT NULL,

我们有一个“访问者”跟踪模式正在运行——当推送时,它似乎会对DB服务器造成一些压力

VISITORS表通过哈希current records 310000标识唯一用户。对散列执行搜索,如果未找到,则添加该散列。以下两个表需要ID

CREATE TABLE  visitors (
    id int(10) UNSIGNED NOT NULL auto_increment,
    ip varchar(25) NOT NULL,
    hash varchar(64) NOT NULL,
    first_visit varchar(32) NOT NULL,
    created_at datetime NOT NULL default '0000-00-00 00:00:00',
    PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;   

ALTER TABLE visitors ADD UNIQUE INDEX (hash);
ALTER TABLE visitors ADD INDEX (created_at);
VISITOR_Visitions表确定用户何时访问,仅当我们可以确定一些推荐源时,当前计数为142000。执行搜索以查找访客id、类型和访问日期。如果没有找到任何内容,则添加该内容。下表中使用了该ID

CREATE TABLE  visitor_visits (
    id int(10) UNSIGNED NOT NULL auto_increment,
    visitor_id int(10) UNSIGNED NOT NULL,
    source varchar(64) NULL DEFAULT NULL DEFAULT NULL,
    medium varchar(64) NULL DEFAULT NULL,
    campaign varchar(256) NULL DEFAULT NULL,
    page varchar(32) NULL DEFAULT NULL,
    landing varchar(32) NULL DEFAULT NULL,
    type enum('fundraiser_view') NULL DEFAULT NULL,
    visit_date date NOT NULL default '0000-00-00',
    created_at datetime NOT NULL default '0000-00-00 00:00:00',
    PRIMARY KEY (id)
  ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

ALTER TABLE visitor_visits ADD UNIQUE INDEX (visitor_id,type,visit_date);
ALTER TABLE visitor_visits ADD CONSTRAINT FK_visits_visitor_id FOREIGN KEY (visitor_id) REFERENCES visitors(id);
页面视图记录单个页面视图,而不是所有页面,只是我们正在跟踪的页面。它可以链接到一个访问者,并且可以引用一个访问者。当前访问量为240万次,其原因是我们在记录单个页面后开始微访问者日志记录。插入/重复查询用于根据已识别用户的查看日期将记录添加到此记录中。由于不需要ID,因此不需要纯查找查询

CREATE TABLE page_views (
  id int(10) UNSIGNED NOT NULL auto_increment,
  page_id int(10) UNSIGNED NOT NULL,
  current_donations decimal(10,2) NOT NULL DEFAULT 0,
  ip varchar(25) NOT NULL,
  hash varchar(32) NOT NULL,
  visitor_id int(10) UNSIGNED NULL DEFAULT NULL AFTER,
  visitor_visit_id int(10) UNSIGNED NULL DEFAULT NULL AFTER,
  page_views int(10) UNSIGNED NOT NULL DEFAULT 0,
  widget_views int(10) UNSIGNED NOT NULL DEFAULT 0,
  view_date date NOT NULL,
  viewed_at datetime NOT NULL default '0000-00-00 00:00:00',
  created_at datetime NOT NULL default '0000-00-00 00:00:00',
  PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

ALTER TABLE page_views ADD UNIQUE INDEX (page_id,view_date,visitor_id,hash);
ALTER TABLE page_views ADD INDEX (visitor_id);
ALTER TABLE page_views ADD INDEX (visitor_visit_id);
ALTER TABLE page_views ADD CONSTRAINT FK_page_views_page_id FOREIGN KEY (page_id)    REFERENCES pages(id);
ALTER TABLE page_views ADD CONSTRAINT FK_page_views_visitor_id FOREIGN KEY (visitor_id)    REFERENCES visitors(id);
ALTER TABLE page_views ADD CONSTRAINT FK_page_views_visit_id FOREIGN KEY (visitor_visit_id) REFERENCES visitor_visits(id);
上周,由于一篇新闻文章,我们的网站吸引了大量的人,而这名访问者的表现受到了限制。我想知道是否有一个明显的优化在那里。这可能是外键约束吗?过度索引?需要更好的索引吗?

试试这个: varchar上的1个索引并不能大大提高性能。 2尝试按日期范围对表进行分区

您没有告诉我们是什么阻碍了您的数据库,所以我猜是InnoDB并发写入。如果不是这样,问题只在于我怀疑的选择,那么您应该向我们展示确切的查询。您可以尝试通过创建一个暂存表,然后将内容从in大容量移动到主表来降低写入性能的影响:

CREATE TABLE page_views_tmp (
  id int(10) UNSIGNED NOT NULL auto_increment,
  page_id int(10) UNSIGNED NOT NULL,
  current_donations decimal(10,2) NOT NULL DEFAULT 0,
  ip varchar(25) NOT NULL,
  hash varchar(32) NOT NULL,
  visitor_id int(10) UNSIGNED NULL DEFAULT NULL AFTER,
  visitor_visit_id int(10) UNSIGNED NULL DEFAULT NULL AFTER,
  page_views int(10) UNSIGNED NOT NULL DEFAULT 0,
  widget_views int(10) UNSIGNED NOT NULL DEFAULT 0,
  view_date date NOT NULL,
  viewed_at datetime NOT NULL default '0000-00-00 00:00:00',
  created_at datetime NOT NULL default '0000-00-00 00:00:00',
  PRIMARY KEY (id)
) ENGINE=MEMORY DEFAULT CHARSET=utf8; 
然后,每隔几秒钟或在该表中有大量行之后执行一次:

START TRANSACTION;

INSERT INTO page_views SELECT * FROM page_views_tmp;
DELETE FROM page_views_tmp;

COMMIT;

您的意思是根据日期范围创建两个或多个表吗?无需创建表,为具有大量数据的单个表创建多个分区有没有办法创建动态分区?或者您必须根据需要添加分区吗?例如,是否可以基于月-年组合独立地添加分区,而不是定义reach组合的每个分区?您可以尝试取消签名,并将其存储为二进制文件