多个连接SQL查询优化

时间:2016-12-09 10:37:02

标签: mysql performance join

我有以下查询:

SELECT 
  COUNT(DISTINCT a0_.id) AS sclr0 
FROM 
  account a0_ 
  INNER JOIN customer c1_ ON (c1_.account = a0_.id) 
  LEFT JOIN sf_user_data s2_ ON (s2_.user_id = a0_.id) 
  LEFT JOIN address a3_ ON (c1_.customer_address = a3_.id) 
WHERE 
  a3_.city IS NOT NULL

产生以下输出:

 sclr0  
+--------+
 298279 

使用以下EXPLAIN:

 id  select_type    table   partitions  type    possible_keys                                 key                    key_len    ref                               rows    filtered    Extra 
+--+---------------+-------+-----------+-------+--------------------------------------------+-----------------------+-----------+--------------------------------+-------+-----------+-------+
1    SIMPLE         c1_     NULL        ALL     UNIQ_81398E097D3656A4,UNIQ_81398E091193CB3F   NULL                   NULL       NULL                              405508   100.00     NULL
1    SIMPLE         a0_     NULL        eq_ref  PRIMARY                                       PRIMARY                8          evoportail.c1_.account            1        100.00     Using index
1    SIMPLE         s2_     NULL        eq_ref  UNIQ_E904BFD1A76ED395                         UNIQ_E904BFD1A76ED395  8          evoportail.c1_.account            1        100.00     Using index
1    SIMPLE         a3_     NULL        eq_ref  PRIMARY                                       PRIMARY                8          evoportail.c1_.customer_address   1         90.00     Using where

表格中的近似行数:

  • 帐号:430000
  • 客户:430000
  • sf_user_data:115000
  • 地址:550000

现在,此查询在3秒内运行。有没有办法加快速度?

CREATE语句:

CREATE TABLE `account` (
  `id` bigint(20) unsigned NOT NULL auto_increment,
  `identifier` varchar(255) collate utf8_bin NOT NULL,
  `hash` varchar(255) collate utf8_bin default NULL,
  `date_create` datetime default NULL,
  `group` varchar(50) collate utf8_bin default NULL,
  `sub_group` varchar(50) collate utf8_bin NOT NULL default 'NULL',
  `date_last_action` datetime default NULL,
  `date_last_connection` datetime default NULL,
  `connection_counter` int(10) unsigned default NULL,
  `connection_since_customer` int(10) unsigned NOT NULL default '0',
  `salt` varchar(255) collate utf8_bin default NULL,
  `roles` longtext collate utf8_bin COMMENT '(DC2Type:array)',
  `is_v3` tinyint(1) NOT NULL default '1',
  `password_token` varchar(255) collate utf8_bin default NULL,
  `password_token_expired_at` datetime default NULL,
  `is_included_in_newsletters` tinyint(1) NOT NULL default '0',
  PRIMARY KEY  (`id`),
  UNIQUE KEY `identifier_UNIQUE` (`identifier`)
) ENGINE=MyISAM AUTO_INCREMENT=434243 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

CREATE TABLE `address` (
  `id` bigint(20) unsigned NOT NULL auto_increment,
  `city` varchar(64) collate utf8_bin default NULL,
  `street` varchar(255) collate utf8_bin default NULL,
  `complement` varchar(128) collate utf8_bin default NULL,
  `zipcode` varchar(16) collate utf8_bin default NULL,
  `country_id` int(11) default NULL,
  `cedex` tinyint(1) NOT NULL default '0',
  `abroad` tinyint(1) NOT NULL default '0',
  PRIMARY KEY  (`id`),
  KEY `IDX_D4E6F81F92F3E70` (`country_id`)
) ENGINE=MyISAM AUTO_INCREMENT=541873 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

CREATE TABLE `customer` (
  `id` bigint(20) unsigned NOT NULL auto_increment,
  `account` bigint(20) unsigned NOT NULL,
  `source` varchar(250) collate utf8_bin NOT NULL default 'DECLARATION',
  `last_source` varchar(250) collate utf8_bin NOT NULL,
  `source_domain_name` varchar(255) collate utf8_bin default NULL,
  `subscription_offer` varchar(255) collate utf8_bin default NULL,
  `formalities_center_address` bigint(20) unsigned default NULL,
  `customer_address` bigint(20) unsigned default NULL,
  `business_address` bigint(20) unsigned default NULL,
  `shipping_address` bigint(20) default NULL,
  `activity` text collate utf8_bin,
  `state` enum('NONE','CREATE','UPDATE','COMPLETE') collate utf8_bin NOT NULL default 'NONE',
  `num_dossier` varchar(255) collate utf8_bin default NULL,
  `email` varchar(255) collate utf8_bin NOT NULL,
  `lastname` varchar(255) collate utf8_bin NOT NULL,
  `firstname` varchar(255) collate utf8_bin NOT NULL,
  `sexe` int(1) NOT NULL default '0',
  `activityset` int(1) NOT NULL default '0',
  `phone` varchar(16) collate utf8_bin NOT NULL,
  `business_name` varchar(255) collate utf8_bin default NULL,
  `payment_method` enum('NONE','CB_OK','CB_KO','CHEQUE_OK','CHEQUE_KO','WAITING','IMPACTPLUS_OK','PRELEV') collate utf8_bin default 'NONE',
  `payment_waiting_comment` text collate utf8_bin,
  `sub_sent_recovery` smallint(6) default '0',
  `transaction_number` varchar(30) collate utf8_bin default NULL,
  `transaction_date` datetime default NULL,
  `properties` set('ACCRE','CFE','WANT_WEBSITE','HAVE_WEBSITE','NEWSLETTER','SUBSCRIBE','OLD_CUSTOMER') collate utf8_bin default NULL,
  `comments` text collate utf8_bin,
  `activity_declaration` varchar(512) collate utf8_bin default NULL COMMENT 'file:///',
  `cfe_center` varchar(255) collate utf8_bin default NULL,
  `date_create` datetime default NULL,
  `date_complete` datetime default NULL,
  `date_subscribe` datetime default NULL,
  `date_next_payement` datetime default NULL,
  `date_ae_subscribe` datetime default NULL,
  `siret` varchar(128) collate utf8_bin default NULL,
  `current_quotation` bigint(20) unsigned default NULL,
  `current_invoice` bigint(20) unsigned default NULL,
  `has_create_quotation` tinyint(1) NOT NULL default '0',
  `has_create_invoice` tinyint(1) NOT NULL default '0',
  `created_by` int(20) NOT NULL default '0',
  `updated_by` int(11) NOT NULL default '0',
  `updated_date` datetime default NULL,
  `abo_running` tinyint(1) NOT NULL default '1',
  `show_bn` tinyint(1) NOT NULL default '1',
  `taxe_type_activite` enum('NULL','ACHAT','SERVICE','BOTH') collate utf8_bin default NULL,
  `taxe_categorie_activite` enum('NULL','COMMERCIALE','ARTISANALE','CIPAV','RSI') collate utf8_bin default NULL,
  `taxe_liberatoire` enum('NULL','OUI','NON') collate utf8_bin default NULL,
  `taxe_statut_accre` enum('NULL','OUI','NON','DK') collate utf8_bin default NULL,
  `know` varchar(50) collate utf8_bin default NULL,
  `sms_relance` int(11) default NULL,
  `fdae` int(1) NOT NULL default '0',
  `display_fdae` tinyint(1) NOT NULL default '0',
  `show_dispense_immat` enum('RCS','RM','RSAC') collate utf8_bin default NULL,
  `show_dispense_immat_city` varchar(255) collate utf8_bin default NULL,
  `subscription_fdae` date default NULL,
  `nbsocial` varchar(30) collate utf8_bin default NULL,
  `atclic` int(1) NOT NULL default '0',
  `merassurance` int(1) NOT NULL default '0',
  `dossier_canceled` tinyint(1) NOT NULL default '0',
  `dossier_canceled_date` datetime default NULL,
  `tva_intra` varchar(20) collate utf8_bin default NULL,
  `site_url` varchar(100) collate utf8_bin default NULL,
  `freeguide` tinyint(1) NOT NULL default '0',
  `hiscox` int(1) NOT NULL default '0',
  `assurland` int(1) NOT NULL default '0',
  `unpaid_advisor` int(11) default NULL,
  `unpaid_date` datetime default NULL,
  `ecl_send` tinyint(1) default NULL,
  `ecl_date` datetime default NULL,
  `birthdateyear` int(11) NOT NULL default '0',
  `quaCategorie` varchar(500) collate utf8_bin default NULL,
  `quaNature` varchar(500) collate utf8_bin default NULL,
  `quaType` varchar(500) collate utf8_bin default NULL,
  `april` int(1) NOT NULL default '0',
  `date_guide` datetime default NULL,
  `no_pub` tinyint(1) NOT NULL default '0',
  `campaign_manual` tinyint(1) NOT NULL default '0',
  `export_matmut` date default NULL,
  `formality_date` datetime default NULL,
  `call_count_commerciaux` int(11) default '0',
  `call_count_assistance` int(11) default '0',
  `call_last` datetime default NULL,
  `prospect` tinyint(1) default NULL,
  `gender_id` int(11) default NULL,
  `birthdate` date default NULL,
  `current_customer_source_history_id` int(11) default NULL,
  `original_customer_source_history_id` int(11) default NULL,
  `bounce` tinyint(1) NOT NULL default '0',
  PRIMARY KEY  (`id`),
  UNIQUE KEY `UNIQ_81398E097D3656A4` (`account`),
  UNIQUE KEY `UNIQ_81398E09E7927C74` (`email`),
  UNIQUE KEY `UNIQ_81398E091193CB3F` (`customer_address`),
  UNIQUE KEY `UNIQ_81398E09507DD4CC` (`business_address`),
  UNIQUE KEY `UNIQ_81398E09BA38C653` (`formalities_center_address`),
  KEY `num_dossier` (`num_dossier`),
  KEY `sub_send_recovery` (`sub_sent_recovery`),
  KEY `dossier_canceled` (`dossier_canceled`),
  KEY `freeguide` (`freeguide`),
  KEY `IDX_81398E09708A0E0` (`gender_id`),
  KEY `IDX_81398E0935655550` (`current_customer_source_history_id`),
  KEY `IDX_81398E0981A1F986` (`original_customer_source_history_id`)
) ENGINE=MyISAM AUTO_INCREMENT=433026 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

CREATE TABLE `sf_user_data` (
  `id` int(11) NOT NULL auto_increment,
  `user_id` bigint(20) unsigned NOT NULL,
  `register_id` int(11) default NULL,
  `insurance_id` int(11) default NULL,
  `activity_started_at` date default NULL,
  `accre_request_accepted` tinyint(1) default NULL,
  `accre_request_accepted_at` date default NULL,
  `declaration_frequency_months` smallint(6) default NULL,
  `declaration_reminder` tinyint(1) default NULL,
  `activities_number` smallint(6) default NULL,
  `computed_main_activity_percent_total` double default NULL,
  `computed_secondary_activity_percent_total` double default NULL,
  `company_address_is_personal_address` tinyint(1) default NULL,
  `register_city` varchar(255) collate utf8_unicode_ci default NULL,
  `invoice_last_increment` smallint(6) NOT NULL default '0',
  `quotation_last_increment` smallint(6) NOT NULL default '0',
  `asset_last_increment` smallint(6) NOT NULL default '0',
  `payplug_parameters` varchar(255) collate utf8_unicode_ci default NULL,
  `displayed_first_connection_dialog` tinyint(1) NOT NULL default '0',
  `displayed_first_invoice_display_dialog` tinyint(1) NOT NULL default '0',
  `payplug_parameters_created_at` date default NULL,
  `payplug_first_payment_at` date default NULL,
  `latest_payplug_http_code` int(11) default NULL,
  `register_number` varchar(255) collate utf8_unicode_ci default NULL,
  `register_code` varchar(255) collate utf8_unicode_ci default NULL,
  `register_bis_city` varchar(255) collate utf8_unicode_ci default NULL,
  `register_bis_number` varchar(255) collate utf8_unicode_ci default NULL,
  `registerBis_id` int(11) default NULL,
  `main_activity_type_id` int(11) default NULL,
  `secondary_activity_type_id` int(11) default NULL,
  `declaration_reminder_popup` tinyint(1) default NULL,
  `declaration_reminder_popup_latest_choice` smallint(6) default NULL COMMENT '1 = Me le rappeler demain, 2 = Ne plus afficher cette alerte',
  `declaration_reminder_popup_latest_choice_date` date default NULL,
  `main_activity_id` int(11) default NULL,
  `secondary_activity_id` int(11) default NULL,
  `primary_socio_economic_classification_id` int(11) default NULL,
  `secondary_socio_economic_classification_id` int(11) default NULL,
  `income_bracket_id` int(11) default NULL,
  `main_activity_custom` varchar(255) collate utf8_unicode_ci default NULL,
  `secondary_activity_custom` varchar(255) collate utf8_unicode_ci default NULL,
  `default_further_information` longtext collate utf8_unicode_ci,
  `gclid` varchar(255) collate utf8_unicode_ci default NULL,
  `main_activity_type_old_id` smallint(6) default NULL,
  `main_activity_nature_old_id` smallint(6) default NULL,
  `secondary_activity_type_old_id` smallint(6) default NULL,
  `secondary_activity_nature_old_id` smallint(6) default NULL,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `UNIQ_E904BFD1A76ED395` (`user_id`),
  UNIQUE KEY `UNIQ_E904BFD1D1E63CD1` (`insurance_id`),
  KEY `IDX_E904BFD14976CB7E` (`register_id`),
  KEY `IDX_E904BFD1DBC024CC` (`registerBis_id`),
  KEY `IDX_E904BFD12E864BE8` (`main_activity_type_id`),
  KEY `IDX_E904BFD132198C62` (`secondary_activity_type_id`),
  KEY `IDX_E904BFD15543A800` (`main_activity_id`),
  KEY `IDX_E904BFD1798B8812` (`secondary_activity_id`),
  KEY `IDX_E904BFD1D17B29D3` (`primary_socio_economic_classification_id`),
  KEY `IDX_E904BFD17758CEBC` (`secondary_socio_economic_classification_id`),
  KEY `IDX_E904BFD1BAF920D3` (`income_bracket_id`)
) ENGINE=MyISAM AUTO_INCREMENT=116384 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

2 个答案:

答案 0 :(得分:0)

似乎这个简单的修正案会更快:

SELECT COUNT(DISTINCT a0_.id) sclr0 
  FROM account a0_ 
  JOIN customer c1_ 
    ON c1_.account = a0_.id
  JOIN address a3_ 
    ON c1_.customer_address = a3_.id

如果数据完整性对您很重要,请考虑切换到InnoDB。

答案 1 :(得分:0)

LEFT JOIN address a3更改为普通JOIN。这样,优化器可以考虑从address开始。并将INDEX(city)添加到address

目前,EXPLAIN显示在3个表中的每个表中都有405K行。 (总共1.2M)通过上面的更改,优化器将从城市索引开始,通过查看,比方说1K行。之后,它将在其他两个表中的每一个中查找1K行。 (总共3K)

LEFT JOIN sf_user_data s2_ ON (s2_.user_id = a0_.id)似乎完全没用;去掉它。 (现在低至2K行)

不要盲目使用(255),请使用合理的数字。这样做,如果identifier不是很大,请将其设为PRIMARY KEY并删除id

极少有6个不同的列,每个列都是UNIQUE。我认为你会因此遇到业务逻辑问题。