当where子句之间的datetime时,MySQL查询速度慢

时间:2013-11-22 13:42:34

标签: php mysql debian

我有一张表格,其中包含17个问题和几个文本块的患者满意度调查(底部创建声明)。它将调查输入数据库时​​设置日期时间字段。我必须能够按时间段(周/月/年)平均运行报告。目前,我正在每周切片中运行查询。

我的查询最多运行16秒,并在运行期间最大化CPU。然后,我必须再进行13个星期的查询以获得全球平均值,然后我对每个选定的医生进行查询14次更多次(可以是0到22次)。

我尝试使用WHERE date >= 'date low' AND date <= 'date high'WHERE date BETWEEN 'date low' AND 'date high',但我尝试了CAST('date' as datetime)无济于事。在分析查询时,似乎将大部分时间花在statistics上,而EXPLAIN似乎在说它没有使用日期扫描索引,但我不知道为什么。

目前大约有1000行,但是当大约有一半的行数时,查询运行正常。从那以后,我得知我在创建表格或者如何形成查询方面都有一个非常糟糕的问题。

注意:在VMWare ESXi 5.1上运行Debian 7.2,具有4GB内存和1个虚拟进程

创建表格

CREATE TABLE IF NOT EXISTS `survey` (
   `id` int(10) NOT NULL AUTO_INCREMENT,
   `datescanned` datetime NOT NULL,
   `physician_fk` int(5) NOT NULL,
   `procedure` varchar(255) DEFAULT NULL,
   `gender` varchar(12) NOT NULL,
   `patientage` varchar(50) NOT NULL DEFAULT 'Not marked',
   `question01_fk` int(1) NOT NULL,
   `question02_fk` int(1) NOT NULL,
   `question03_fk` int(1) NOT NULL,
   `question04_fk` int(1) NOT NULL,
   `question05_fk` int(1) NOT NULL,
   `question06_fk` int(1) NOT NULL,
   `question07_fk` int(1) NOT NULL,
   `question08_fk` int(1) NOT NULL,
   `question09_fk` int(1) NOT NULL,
   `question10_fk` int(1) NOT NULL,
   `question11_fk` int(1) NOT NULL,
   `question12_fk` int(1) NOT NULL,
   `question13_fk` int(1) NOT NULL,
   `question14_fk` int(1) NOT NULL,
   `question15_fk` int(1) NOT NULL,
   `question16_fk` int(1) NOT NULL,
   `question17_fk` int(1) NOT NULL,
   `notes` text,
   `email` varchar(256) DEFAULT NULL,
   `name` varchar(256) DEFAULT NULL,
   `qanotes` text,
   `referredby` varchar(255) DEFAULT NULL,
   `edited` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
   `editedby_fk` int(5) NOT NULL DEFAULT '1',
   `viewed` tinyint(1) NOT NULL DEFAULT '0',
   `handled` int(1) NOT NULL DEFAULT '0',
   `archived` tinyint(1) NOT NULL DEFAULT '0',
    PRIMARY KEY (`id`),
    KEY `fk_physicianid` (`physician_fk`),
    KEY `fk_question01id` (`question01_fk`),
    KEY `fk_question02id` (`question02_fk`),
    KEY `fk_question03id` (`question03_fk`),
    KEY `fk_question04id` (`question04_fk`),
    KEY `fk_question05id` (`question05_fk`),
    KEY `fk_question06id` (`question06_fk`),
    KEY `fk_question07id` (`question07_fk`),
    KEY `fk_question08id` (`question08_fk`),
    KEY `fk_question09id` (`question09_fk`),
    KEY `fk_question10id` (`question10_fk`),
    KEY `fk_question11id` (`question11_fk`),
    KEY `fk_question12id` (`question12_fk`),
    KEY `fk_question13id` (`question13_fk`),
    KEY `fk_question14id` (`question14_fk`),
    KEY `fk_question15id` (`question15_fk`),
    KEY `fk_question16id` (`question16_fk`),
    KEY `fk_question17id` (`question17_fk`),
    KEY `fk_editedbyid` (`editedby_fk`),
    KEY `handled` (`handled`),
    KEY `scanned_index` (`datescanned`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=991 ; 

注意:所有问题都指向同一个表

选择查询

SELECT  q01.worth, q02.worth, q03.worth, q04.worth, q05.worth, q06.worth, q07.worth,
q08.worth, q09.worth, q10.worth, q11.worth, q12.worth, q13.worth, q14.worth, q15.worth,
q16.worth, q17.worth

FROM survey s, answer q01, answer q02, answer q03, answer q04,
answer q05, answer q06, answer q07, answer q08, answer q09, answer q10, answer q11,
answer q12, answer q13, answer q14, answer q15, answer q16, answer q17 

WHERE s.archived !=1 AND q01.id = s.question01_fk AND q02.id = s.question02_fk
AND q03.id = s.question03_fk AND q04.id = s.question04_fk AND q05.id = s.question05_fk
AND q06.id = s.question06_fk AND q07.id = s.question07_fk AND q08.id = s.question08_fk 
AND q09.id = s.question09_fk AND q10.id = s.question10_fk AND q11.id = s.question11_fk 
AND q12.id = s.question12_fk AND q13.id = s.question13_fk AND q14.id = s.question14_fk
AND q15.id = s.question15_fk AND q16.id = s.question16_fk AND q17.id = s.question17_fk

AND s.datescanned >=  '2013-11-18 00:00:00' AND s.datescanned <=  '2013-11-25 23:59:59';

注意:我已尝试使用和不使用INNER JOIN进行question_fk

编辑:我注意到我需要重新考虑我的结构。我将继续努力,如果修复它,请更新或关闭此帖子。感谢那些到目前为止评论过的人。

编辑2:这是一个结构问题。拆分问题并映射到他们将整个报告从3分钟以上丢弃到20秒以下。谢谢所有提供指导的人。

1 个答案:

答案 0 :(得分:1)

虽然技术上没有回答这个问题,但这是我要使用的设计:

  • 调查: survey_id ,日期扫描等......
  • 问题: question_id ,说明等......
  • SURVEY_QUESTION: survey_id question_id

以粗体显示主键。请注意,SURVEY_QUESTION表的复合键包含SURVEY的外键和QUESTION的外键。

为了获得所有问题的所有调查,你应该做这样的事情

SELECT * FROM survey s
JOIN survey_question sq on s.survey_id = sq.survey_id
JOIN question q on sq.question_id = q.question_id

这比每个问题都有一个列更快,更灵活。