проблема с производительностью mysql - PullRequest
0 голосов
/ 10 июня 2009

У меня есть таблица с именами контактов, в которой используется почти 1,2 миллиона записей. Движок MyIsam всякий раз, когда мы запрашиваем эту таблицу, mysql зависает, поэтому теперь мы пробуем свои силы с движком Innodb, чтобы, если он замедляется, но не зависает для других

Итак, мы хотим ускорить работу с Myisam. Мы опробовали множество индексов для этой таблицы, но она не работает и система зависает

Что нужно сделать, чтобы сделать его быстрее и не зависать в системе

Это таблица:

CREATE TABLE `contacts` (
  `id` varchar(36) NOT NULL,
  `deleted` tinyint(1) NOT NULL default '0',
  `date_entered` datetime NOT NULL default '0000-00-00 00:00:00',
  `date_modified` datetime NOT NULL default '0000-00-00 00:00:00',
  `modified_user_id` varchar(36) default NULL,
  `assigned_user_id` varchar(36) default NULL,
  `created_by` varchar(36) default NULL,
  `team_id` varchar(36) default NULL,
  `salutation` varchar(5) default NULL,
  `first_name` varchar(100) default '',
  `last_name` varchar(100) default '',
  `username` varchar(25) default '',
  `lead_source` varchar(100) default NULL,
  `title` varchar(50) default NULL,
  `department` varchar(100) default NULL,
  `reports_to_id` varchar(36) default NULL,
  `birthdate` date default NULL,
  `do_not_call` char(3) default '0',
  `phone_home` varchar(25) default NULL,
  `phone_mobile` varchar(25) default NULL,
  `phone_work` varchar(25) default '',
  `phone_other` varchar(25) default NULL,
  `phone_fax` varchar(25) default '',
  `email1` varchar(100) default '',
  `email2` varchar(100) default NULL,
  `assistant` varchar(75) default NULL,
  `assistant_phone` varchar(25) default NULL,
  `email_opt_out` char(3) default 'off',
  `primary_address_street` varchar(150) default NULL,
  `primary_address_city` varchar(100) default NULL,
  `primary_address_state` varchar(100) default NULL,
  `primary_address_postalcode` varchar(20) default NULL,
  `primary_address_country` varchar(100) default NULL,
  `alt_address_street` varchar(150) default NULL,
  `alt_address_city` varchar(100) default NULL,
  `alt_address_state` varchar(100) default NULL,
  `alt_address_postalcode` varchar(20) default NULL,
  `alt_address_country` varchar(100) default NULL,
  `description` text,
  `portal_name` varchar(255) default NULL,
  `portal_active` tinyint(1) NOT NULL default '0',
  `portal_app` varchar(255) default NULL,
  `salesforceid` varchar(36) default NULL,
  `phone_direct` varchar(25) default NULL,
  `invalid_email` tinyint(1) default '0',
  `parent_is_lead` char(3) default 'no',
  `advisory_board_member` varchar(25) default NULL,
  `direct_marketing` varchar(25) default NULL,
  `efx_id` varchar(36) default NULL,
  `fax_opt_out` char(3) default 'off',
  `ppc_keyword` varchar(50) default NULL,
  `status` varchar(25) default NULL,
  `web_form` varchar(50) default NULL,
  `efx_export_date` datetime default NULL,
  `bmtn` varchar(225) default '',
  `employee_location` varchar(50) default NULL,
  `pronunciation` varchar(250) default NULL,
  `duplicate_of` varchar(36) default NULL,
  `job_category` varchar(50) default NULL,
  `last_ska_upload_key` varchar(50) default NULL,
  `persid` varchar(36) default NULL,
  `last_web_upload_key` varchar(50) default NULL,
  `last_webinar_upload_key` varchar(50) default NULL,
  `primary_address_latitude` float default NULL,
  `primary_address_longitude` float default NULL,
  `first_name_soundex` varchar(30) default NULL,
  `last_name_soundex` varchar(30) default NULL,
  `primary_address_street_soundex` varchar(30) default NULL,
  `campaign_id` varchar(36) default NULL,
  `portal_password` varchar(32) default NULL,
  `pss_branch` varchar(40) default NULL,
  `pss_id` int(12) default NULL,
  `source_detail` varchar(100) default NULL,
  `source` varchar(100) default NULL,
  `pss_region` varchar(30) default NULL,
  `source_added` datetime default NULL,
  `terminated_user` char(3) default 'off',
  `invite_opt_out` char(3) default 'off',
  `newsletter_opt_out` char(3) default 'off',
  `stream_opt_out` char(3) default 'off',
  PRIMARY KEY  (`id`),
  KEY `idx_contacts_del_last` (`deleted`,`last_name`),
  KEY `idx_cont_del_reports` (`deleted`,`reports_to_id`,`last_name`),
  KEY `idx_contact_del_team` (`deleted`,`team_id`),
  KEY `idx_contact_salesforceid` (`salesforceid`),
  KEY `idx_contacts_username` (`username`),
  KEY `idx_email_opt_out` (`email_opt_out`),
  KEY `idx_primary_address_street` (`primary_address_street`),
  KEY `idx_primary_address_city` (`primary_address_city`),
  KEY `idx_primary_address_state` (`primary_address_state`),
  KEY `idx_primary_address_postalcode` (`primary_address_postalcode`),
  KEY `idx_primary_address_country` (`primary_address_country`),
  KEY `idx_modified_user_id` (`modified_user_id`),
  KEY `idx_assigned_user_id` (`assigned_user_id`),
  KEY `idx_created_by` (`created_by`),
  KEY `idx_team_id` (`team_id`),
  KEY `idx_reports_to_id` (`reports_to_id`),
  KEY `idx_contacts_efx_id` (`efx_id`),
  KEY `idx_contacts_title1` (`title`,`deleted`),
  KEY `idx_contacts_email1` (`email1`),
  KEY `idx_contacts_email2` (`email2`),
  KEY `idx_contacts_job_category` (`job_category`),
  KEY `idx_contacts_first_name_sdx` (`first_name_soundex`),
  KEY `idx_contacts_primary_street_sdx` (`primary_address_street_soundex`),
  KEY `idx_contacts_last_name_sdx` (`last_name_soundex`),
  KEY `idx_contacts_portal_name` (`portal_name`),
  KEY `idx_contacts_portal_active` (`portal_active`),
  KEY `idx_contacts_del_last_first` (`deleted`,`last_name`,`first_name`),
  KEY `idx_contacts_del_first` (`deleted`,`first_name`),
  KEY `idx_pss_id` (`pss_id`),
  KEY `idx_phone_work_last_name_first_name_deleted` (`phone_work`,`last_name`,`first_name`,`deleted`),
  KEY `idx_phone_work_last_name_first_name_deleted_sdx` (`phone_work`,`last_name_soundex`,`first_name_soundex`,`deleted`),
  KEY `idx_email1_last_name_first_name_deleted` (`email1`,`last_name`,`first_name`,`deleted`),
  KEY `idx_email1_last_name_first_name_deleted_sdx` (`email1`,`last_name_soundex`,`first_name_soundex`,`deleted`),
  KEY `idx_phone_fax_last_name_first_name_deleted` (`phone_fax`,`last_name`,`first_name`,`deleted`),
  KEY `idx_phone_fax_last_name_first_name_deleted_sdx` (`phone_fax`,`last_name_soundex`,`first_name_soundex`,`deleted`),
  KEY `idx_phone_work_last_name_deleted` (`phone_work`,`last_name`,`deleted`),
  KEY `idx_phone_work_last_name_deleted_sdx` (`phone_work`,`last_name_soundex`,`deleted`),
  KEY `idx_email1_last_name_deleted` (`email1`,`last_name`,`deleted`),
  KEY `idx_email1_last_name_deleted_sdx` (`email1`,`last_name_soundex`,`deleted`),
  KEY `idx_phone_fax_last_name_deleted` (`phone_fax`,`last_name`,`deleted`),
  KEY `idx_phone_fax_last_name_deleted_sdx` (`phone_fax`,`last_name_soundex`,`deleted`),
  KEY `idx_email1_first_name_deleted` (`email1`,`first_name`,`deleted`),
  KEY `idx_email1_first_name_deleted_sdx` (`email1`,`first_name_soundex`,`deleted`),
  KEY `idx_phone_fax_first_name_deleted` (`phone_fax`,`first_name`,`deleted`),
  KEY `idx_phone_fax_first_name_deleted_sdx` (`phone_fax`,`first_name_soundex`,`deleted`),
  KEY `idx_email1_deleted` (`email1`,`deleted`),
  KEY `idx_last_name_first_name_deleted_sdx` (`last_name_soundex`,`first_name_soundex`,`deleted`),
  KEY `idx_phone_mobile_deleted` (`phone_mobile`,`deleted`,`id`),
  KEY `idx_first_name_bmtn` (`first_name`,`bmtn`),
  KEY `idx_first_name_bmtn_email1` (`first_name`,`bmtn`,`email1`),
  KEY `idx_bmtn_email1` (`bmtn`,`email1`),
  KEY `idx_deleted` (`deleted`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

-

SELECT acc.id, acc.name, con_reports_to.first_name, con_reports_to.last_name
from contacts
left join accounts_contacts a_c on a_c.contact_id = '9802f40d-78bb-8dd4-dfaa-43f1064ccd5e' and a_c.deleted=0
left join accounts acc on a_c.account_id = acc.id and acc.deleted=0
left join contacts con_reports_to on con_reports_to.id = contacts.reports_to_id
where contacts.id = '9802f40d-78bb-8dd4-dfaa-43f1064ccd5e'

Ответы [ 2 ]

1 голос
/ 10 июня 2009

Я подозреваю, что утверждение "всякий раз, когда мы запрашиваем эту таблицу, mysql зависает", является перекупом - например, с MyISAM, SELECT COUNT(*) FROM TheTable должен быть очень быстрым, по сути "несмотря ни на что". Конечно, некоторые запросы будут медленными - особенно если таблица не будет правильно проиндексирована для запросов или если предполагаемый оптимизатор MySQL выбирает неправильную стратегию (но вы могли бы дать ей подсказки).

Почему бы вам не показать нам CREATE TABLE (включая индексы), пару запросов, которые занимают слишком много времени, в идеале точную меру того, сколько времени они занимают, и вывод EXPLAIN SELECT (& c) для этих парных запросов - держу пари, мы могли бы действительно быть тогда чем-то полезными!

Редактировать: CREATE TABLE по существу показывает, что таблица слишком "широкая" - слишком много столбцов - чтобы ожидать достойной производительности (даже если не было показано ни одного запроса). Схема нуждается в переработке, разбивая куски этой огромной монолитной таблицы (например, информацию, связанную с адресом) на другие вспомогательные таблицы. Как именно это лучше всего сделать, зависит полностью от запросов, которые наиболее важны для оптимизации, поэтому, не зная этих запросов, я даже не собираюсь пытаться выполнить задачу.

Снова отредактируйте: поэтому запрос был опубликован и использует другие таблицы, accounts и account_contacts, а также чрезвычайно широкую описанную contacts; отправленный запрос (пытающийся разобраться в этом с помощью форматирования & c):

SELECT acc.id, acc.name, con_reports_to.first_name, con_reports_to.last_name
FROM contacts 
LEFT JOIN accounts_contacts a_c 
          ON a_c.contact_id = '9802f40d-78bb-8dd4-dfaa-43f1064ccd5e' AND
             a_c.deleted=0 
LEFT JOIN accounts acc 
          ON a_c.account_id = acc.id AND 
             acc.deleted=0
LEFT JOIN contacts con_reports_to 
          ON con_reports_to.id = contacts.reports_to_id
WHERE contacts.id = '9802f40d-78bb-8dd4-dfaa-43f1064ccd5e'

Почему LEFT JOIN здесь вместо нормальных INNER присоединяется? Возможно ли в каждом случае, что в правой части таблицы нет соответствующей строки? Например, если в a_c нет строки с заданными значениями для contact_id и deleted, то все поля a_c в первом LEFT JOIN будут NULL, поэтому соответствия не может быть для acc либо: важно ли в этом случае выделять NULL, NULL в качестве первых двух столбцов? Более того, условия JOIN для a_c и acc вообще не ссылаются на contacts, так что это будет декартово произведение: каждая строка, выбранная из acc, если таковая имеется, будет сопряжена с каждой выбранной строкой от con_reports_to. Таким образом, запрос a_c / acc может быть полностью отделен от запроса на contacts и con_reports, предположительно значительно облегчая запрос (два логически отдельных результата, конечно, могут быть легко снова объединены в клиенте).

Что говорит EXPLAIN SELECT для этого сложного запроса и что он говорит для двух более легких отдельных, которые я предлагаю? Какие индексы есть в таблицах accounts и account_contact?

0 голосов
/ 10 июня 2009

горизонтальное расщепление? хотя я думаю, что 1,2 миллиона записей - это не так много, чтобы ввести горизонтальное разделение ... попробуйте найти нижнюю шею ... также проблема может быть связана с вашим оборудованием, например, жесткий диск почти заполнен и т. д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...