remove/optimize redundant indices

Anything you want added or changed in future versions of ZoneMinder? Post here and there's a chance it will get in! Search to make sure it hasn't already been requested.
Post Reply
carteriii
Posts: 65
Joined: Sun Oct 28, 2007 3:13 pm

remove/optimize redundant indices

Post by carteriii »

I see that each table has declared both a PRIMARY KEY and a UNIQUE KEY on the Id column of each table. I believe this is unnecessarily redundant. Unless MySQL has an optimization to ignore one of these indices entirely, I believe this is only causing inserts and updates (though the Id's are never updated) to be slightly slower since each index must be maintained separately for every row in the table. For what it's worth, you can find a query to find all redundant queries here: http://forge.mysql.com/snippets/view.php?id=45

I'd also like to point out that the Events table defines a key on the combination of Id and MonitorId. This is also redundant with the other keys that begin with Id. Purely as an optimization, though at the cost of some confusion, you could define the primary key to be on ('Id', 'MonitorId') and then eliminate both of the other single indices on ('Id'). This can be done because an index on more than one column can always be used to query only the first column of the index. By contrast, an index on ('Id', 'MonitorId') cannot be used to query for only the MonitorId.
User avatar
zoneminder
Site Admin
Posts: 5215
Joined: Wed Jul 09, 2003 2:07 pm
Location: Bristol, UK
Contact:

Post by zoneminder »

Thanks for these suggestions. As the database has evolved rather than been planned from day one I do sometimes find redundant things like this. Thanks for taking the time to post such a thorough report.
Phil
User avatar
zoneminder
Site Admin
Posts: 5215
Joined: Wed Jul 09, 2003 2:07 pm
Location: Bristol, UK
Contact:

Post by zoneminder »

Just as a query on your second point. If the Events table had it's primary key changed to Id, MonitorId instead of Id do you know how/if that would affect the auto increments?
Phil
carteriii
Posts: 65
Joined: Sun Oct 28, 2007 3:13 pm

Post by carteriii »

I believe it "should" be fine, but I'm more of a SQL Server/Oracle, so I'll test with MySQL for you this weekend (if not before) and let you know.
User avatar
zoneminder
Site Admin
Posts: 5215
Joined: Wed Jul 09, 2003 2:07 pm
Location: Bristol, UK
Contact:

Post by zoneminder »

Thanks, that would be useful.

I deleted the additional indices this afternoon and it has (as I guess would be expected) reduced the relevant .MYI files by about 50% so a result there as it doesn't seem to be optimising one out.

In case anyone else wants to do it (with the proviso that I have only just done so there may be unforeseen consequences though I would not see a reason why) just go into mysql, select your zm database and type

Code: Select all

alter table Config drop index `UC_Name`;
alter table Controls drop index `UC_Id`;
alter table Devices drop index `UC_Id`;
alter table Events drop index `UC_Id`;
alter table Frames drop index `UC_Id`;
alter table Users drop index `UC_Id`;
alter table ZonePresets drop index `UC_Id`;
alter table Zones drop index `UC_Id`;
It may take a couple of minutes and ideally you might want to stop ZM first and then restart it later.
Phil
carteriii
Posts: 65
Joined: Sun Oct 28, 2007 3:13 pm

Post by carteriii »

I just ran a quick test on the primary key, and while certainly not exhaustive, I think it confirms that a primary key on multiple columns, one of which is an auto_increment, should work just fine. The simple script I ran is below. Note that I was not able to put the primary key column definitions in quotes as is the convention in zm_create.sql. Maybe it's just my version of MySQL, but ('Id','MonitorId') failed to parse, but (Id, MonitorId) parsed just fine.

Code: Select all

DROP TABLE IF EXISTS `Events`;

CREATE TABLE `Events` (
  `Id` int(10) unsigned NOT NULL auto_increment,
  `MonitorId` int(10) unsigned NOT NULL default '0',
  `Name` varchar(64) NOT NULL default '',
  PRIMARY KEY  (Id, MonitorId)
) DEFAULT CHARSET=latin1;

INSERT INTO Events (MonitorId, Name) VALUES (1, 'Should Insert Fine');
INSERT INTO Events (MonitorId, Name) VALUES (1, 'Second Event for Monitor One');
INSERT INTO Events (Name) VALUES ('Should Default Monitor to Zero');
INSERT INTO Events (Name) VALUES ('Second Event with Monitor Zero');
INSERT INTO Events (MonitorId, Name) VALUES (0, 'Third Event for Monitor Zero');
SELECT * FROM Events;
User avatar
zoneminder
Site Admin
Posts: 5215
Joined: Wed Jul 09, 2003 2:07 pm
Location: Bristol, UK
Contact:

Post by zoneminder »

Thanks. Mysql tends to use the funny backquotes rather than regular single quotes so maybe you just tried the wrong sort :)
Phil
Post Reply