2016-12-09 3 views
0

У меня есть следующий запрос:несколько объединений оптимизации SQL запросов

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; 
+0

В дополнение к EXPLAIN, вопросы такого характера ВСЕГДА требуют операторов CREATE TABLE для ВСЕХ соответствующих таблиц. Это также невероятно необычно для таблиц OUTER JOIN, из которых вы не выбираете столбцы. – Strawberry

+0

Почему вы думаете, что 3 секунды медленно? – Rahul

+0

@Strawberry отредактировал вопрос с операторами создания – VaN

ответ

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

Это не эквивалентны. Он может (должен) полностью избавиться от 'left join' до' s2_', но не заменять его 'join'. Также 'city' может быть' null', поэтому условие 'where' должно оставаться. – Solarflare

+0

@Solarflare correct – Strawberry

+0

Ничего себе, это было быстро. Не уверен, увидели ли вы свое редактирование на мой комментарий. Вы также должны соблюдать условие 'where' (все города могут быть« пустыми », если они захотят и будут рассчитывать сейчас, но не должны). – Solarflare

0

Изменение LEFT JOIN address a3 до JOIN. Таким образом, оптимизатор может рассмотреть возможность начать с address. И добавьте INDEX(city) в address.

В настоящее время EXPLAIN показывает удары 405K строк в каждом из 3 таблиц. (Всего 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. Из-за этого вы столкнетесь с проблемами бизнес-логики.

Смежные вопросы