我的SQL查询工作很慢。花3秒钟检查3万行

时间:2016-08-02 16:23:18

标签: php mysql database eloquent

我有一个MySQL数据库,我有3个表,其中每个表将有近30,000条记录。这是我的表结构的样子,我的表结构有什么问题吗?

我有一个名为leads的表,其结构如下:

CREATE TABLE `rico16_leads` (
  `id` int(10) unsigned NOT NULL,
  `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `email` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `password` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `mobile` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `mobilealt` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `address` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `state` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `city` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `country` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `investment` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `profileimage` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `callback` datetime DEFAULT NULL,
  `conversation` text COLLATE utf8_unicode_ci NOT NULL,
  `dob` date DEFAULT NULL,
  `pan_card` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `broking_from` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `status` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `user_id` int(10) unsigned DEFAULT NULL,
  `active` smallint(6) NOT NULL DEFAULT '1',
  `lead_existence` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT 'exist',
  `assign_at` datetime DEFAULT NULL,
  `register_at` datetime NOT NULL,
  `remember_token` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
  `used_status` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT 'unused',
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB AUTO_INCREMENT=25883 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

然后我有另一个名为status的表(这里我也存储了一些服务),看起来像:

CREATE TABLE `rico16_status` (
      `id` int(10) unsigned NOT NULL,
      `status` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
      `status_id` int(11) NOT NULL,
      `plans` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
      `details` text COLLATE utf8_unicode_ci NOT NULL,
      `termscondition` text COLLATE utf8_unicode_ci NOT NULL,
      `price` int(11) NOT NULL,
      `showdropdown` int(11) NOT NULL DEFAULT '0',
      `invoicefilterdropdown` int(11) NOT NULL DEFAULT '0',
      `trash` int(11) NOT NULL DEFAULT '0',
      `active` int(11) NOT NULL DEFAULT '1',
      `created_at` timestamp NULL DEFAULT NULL,
      `updated_at` timestamp NULL DEFAULT NULL
    ) ENGINE=InnoDB AUTO_INCREMENT=80 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

现在基于这两个表我有另一个表名leads_services,它看起来像下面的截图。此处lead_idstatus_idinvoice_id是外键:

CREATE TABLE `rico16_lead_services` (
      `id` int(10) unsigned NOT NULL,
      `invoice_id` int(10) unsigned DEFAULT NULL,
      `status_id` int(10) unsigned DEFAULT NULL,
      `lead_id` int(10) unsigned DEFAULT NULL,
      `service_startdate` datetime DEFAULT NULL,
      `service_enddate` datetime DEFAULT NULL,
      `active` smallint(6) NOT NULL DEFAULT '1',
      `callby_call` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
      `callby_sms` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
      `callby_email` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
      `review` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '1',
      `deleted_at` timestamp NULL DEFAULT NULL,
      `trash` int(11) NOT NULL DEFAULT '0',
      `created_at` timestamp NULL DEFAULT NULL,
      `updated_at` timestamp NULL DEFAULT NULL
    ) ENGINE=InnoDB AUTO_INCREMENT=31761 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

我还有一个表,通过它我可以获取conversation的数据,我记录了与各个潜在客户的所有对话。这是它的样子:

    CREATE TABLE `rico16_conversations` (
      `id` int(10) unsigned NOT NULL,
      `user_id` int(10) unsigned DEFAULT NULL,
      `lead_id` int(10) unsigned DEFAULT NULL,
      `conversation` text COLLATE utf8_unicode_ci NOT NULL,
      `created_at` timestamp NULL DEFAULT NULL,
      `updated_at` timestamp NULL DEFAULT NULL
    ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

现在我不确定我是否在任何结构方面做出任何错误。但是我的简单连接查询需要很长时间才能获取数据。而且我相信数据会增加到数百万条记录,但是这些小数据也会很慢,这让我很担心。

以下是与这些表格中的每一个的关系:

ALTER TABLE `rico16_leads`
  ADD PRIMARY KEY (`id`),
  ADD UNIQUE KEY `leads_mobile_unique` (`mobile`),
  ADD KEY `user_id` (`user_id`) USING BTREE;

ALTER TABLE `rico16_leads`
  MODIFY `id` int(10) unsigned NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=25883;

ALTER TABLE `rico16_status`
  ADD PRIMARY KEY (`id`);

ALTER TABLE `rico16_status`
  MODIFY `id` int(10) unsigned NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=80;

ALTER TABLE `rico16_lead_services`
  ADD PRIMARY KEY (`id`);

ALTER TABLE `rico16_lead_services`
  MODIFY `id` int(10) unsigned NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=31761;

ALTER TABLE `rico16_conversations`
  MODIFY `id` int(10) unsigned NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=2;

ALTER TABLE `rico16_conversations`
  ADD PRIMARY KEY (`id`),
  ADD KEY `conversations_user_id_foreign` (`user_id`),
  ADD KEY `conversations_lead_id_foreign` (`lead_id`);

我不确定是否需要INDEX才能使其正确,以及我应该使用哪个字段。我已经尝试了谷歌,但无法找到它。

以下是我正在使用的查询:

Lead::where(function($query) use($loginuser){
                        $loginuser->roles[0]->name == 'administrator' ? $query->where('user_id', '!=', 'NULL') : $query->where('user_id', '=', Auth::user()->id);
                     })
                     ->where('active', 1)
                     ->with(['services', 'services.showstatus', 'services.showstatus.parent', 'users','conversationdetail'])
                     ->whereHas('services', function($query){
                          $query->where('updated_at','>=', DateTimeHelpers::TodayDateStart())
                                ->where('updated_at','<=', DateTimeHelpers::TodayDateEnd());
                     })
                     ->orderBy('id','desc');

或者您可以参考以下查询。

select * 
from `rico16_leads`  
where (`user_id` != ?)  
  and `active` = ?  
  and exists (select *  
              from `rico16_lead_services` 
              where `rico16_lead_services`.`lead_id` = `rico16_leads`.`id`
                and `updated_at` >= ? and `updated_at` <= ? 
      ) 
order by `id` desc

以下是我尝试使用的JOIN查询版本,执行时间超过3.5秒:

SELECT *  
FROM `rico16_leads` as rl  
LEFT JOIN rico16_lead_services as rls  
  ON rls.lead_id = rl.id  
WHERE user_id != '' AND rl.active = '1'  
  and rls.updated_at >= '2016-07-27 00:00:00'  
  and rls.updated_at < '2016-08-02 23:59:59'  
ORDER BY rl.id DESC

谢谢(提前)!

0 个答案:

没有答案