提高MySQL查询性能 – 记录太多

我正在使用MySQL RDMS作为联系人管理系统.现在,我的数据库增长了一天,包含超过100万条记录.在管理过程中检查重复的电话号码成为一个大问题.当我在整个数据库中搜索电话号码时,我的服务器负载急剧增加.由于我不想在数据库中保留重复的电话记录,因此我常常检查整个数据库中是否存在电话号码,这会导致我的应用程序变慢.我的问题:如何以高性能改进查询整个数据库.

phone1 -> Datatype Varchar(10)

我尝试索引,它为我做了一点.任何其他方法来提高我的系统的性能.

表结构:

CREATE TABLE `phone_directory` (
  `lead_id` INT(9) UNSIGNED NOT NULL AUTO_INCREMENT,
  `list_id` BIGINT(14) UNSIGNED DEFAULT NULL,
  `gmt_offset_now` DECIMAL(4,2) DEFAULT '0.00',
  `first_name` VARCHAR(30) DEFAULT NULL,
  `middle_initial` CHAR(1) DEFAULT NULL,
  `last_name` VARCHAR(30) DEFAULT NULL,
  `address1` VARCHAR(100) DEFAULT NULL,
  `address2` VARCHAR(100) DEFAULT NULL,
  `address3` VARCHAR(100) DEFAULT NULL,
  `city` VARCHAR(50) DEFAULT NULL,
  `state` CHAR(2) DEFAULT NULL,
  `postal_code` VARCHAR(10) DEFAULT NULL,
  `phone1` VARCHAR(12) DEFAULT NULL,
  `phone2` VARCHAR(12) DEFAULT NULL,
  `phone3` VARCHAR(12) DEFAULT NULL,
  `email` VARCHAR(70) DEFAULT NULL,
  `fax_number` VARCHAR(255) DEFAULT NULL,
  `manager_name` VARCHAR(255) DEFAULT NULL,
  `status` VARCHAR(6) DEFAULT NULL,
  PRIMARY KEY (`lead_id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

查询:

SELECT * FROM phone_directory WHERE phone1 IN ('315XXXXXXX','0315XXXXXXX');

SELECT * FROM phone_directory WHERE phone2 IN ('315XXXXXXX','0315XXXXXXX');

SELECT * FROM phone_directory WHERE phone3 IN ('315XXXXXXX','0315XXXXXXX');

解决方法:

我建议没有三列phone1,phone2和phone3,但有一个相关的电话表,并让你的数据完全标准化(或进一步标准化):

 CREATE TABLE `phone_directory` (
   `lead_id` INT(9) UNSIGNED NOT NULL AUTO_INCREMENT,
   `list_id` BIGINT(14) UNSIGNED DEFAULT NULL,
   `gmt_offset_now` DECIMAL(4,2) DEFAULT '0.00',
   `first_name` VARCHAR(30) DEFAULT NULL,
   `middle_initial` CHAR(1) DEFAULT NULL,
   `last_name` VARCHAR(30) DEFAULT NULL,
   `address1` VARCHAR(100) DEFAULT NULL,
   `address2` VARCHAR(100) DEFAULT NULL,
   `address3` VARCHAR(100) DEFAULT NULL,
   `city` VARCHAR(50) DEFAULT NULL,
   `state` CHAR(2) DEFAULT NULL,
   `postal_code` VARCHAR(10) DEFAULT NULL,
   `email` VARCHAR(70) DEFAULT NULL,
   `fax_number` VARCHAR(255) DEFAULT NULL,
   `manager_name` VARCHAR(255) DEFAULT NULL,
   `status` VARCHAR(6) DEFAULT NULL,
   PRIMARY KEY (`lead_id`)
 ) ENGINE=INNODB DEFAULT CHARSET=utf8;

 CREATE TABLE phones
 (
     lead_id INT(9) NOT NULL REFERENCES phone_directory(lead_id),
     phone VARCHAR(12) NOT NULL,  
     priority tinyint DEFAULT 1,  -- If you need to give them priorities (1, 2, 3, ...), or sort them
     CONSTRAINT unique_phones UNIQUE(phone), -- You don't want repetead telephones. This enforces it.
     PRIMARY KEY(lead_id, phone)  -- Covering index + clustering... for the sake of efficiency
 ) ;

您现在的支票仅限于:

SELECT 
    lead_id, phone 
FROM 
    phones 
WHERE 
    phone IN ('315XXXXXXX','0315XXXXXXX');

平均而言,这将快3倍…并且对于给定的lead_id,您可以拥有0,1,2,3或任意数量的电话,并且您的UNIQUE约束强制执行唯一性,因此,如果您的某些点出现错误应用程序,数据库可以帮助您避免错误.

dbfiddle here

注1:一家公司有超过3个电话号码并不奇怪:你覆盖所有基地.

注意2:由于电话号码不会使用非ASCII字符,因此您可以通过指定单字符排序规则(例如latin1_bin)来节省一些空间(并且速度略有提高,因为数据将会移动更少).

dbfiddle here

上一篇:unix/linux环境中Oracle RAC OFF和RAC ON


下一篇:MySQL中的数据库是Oracle中的模式:我不理解这种说法