Answer the question
In order to leave comments, you need to log in
MySQL table architecture: strings or numbers
Gentlemen, I have a dilemma.
I reorganize the table in the database, this table has a column (hereinafter referred to as services) which is used to store the status of an object in some categories. Status is a number from 0 to 3. The number of categories can change (there are currently 11).
That is, for example:
Object 1:
Category 1 - Status 3
Category 2 - Status 1
Category 3 - Status 2
...
Object 2:
Category 1 - Status 1
Category 2 - Status 3
Category 3 - Status 2
...
...
(1, '31200000000'),
(2, '13200000000')
...
...
(1, 39), #39 10 = 213 4
(2, 45) #45 10 = 231 4
...
services mod 4 service + 1 div 4 service
/* Запрос 1 */ SELECT * FROM `test_b` WHERE `services` LIKE '___2%';
/* Запрос 2 */ SELECT * FROM `test_a` WHERE (`services` MOD 256) DIV 64 = 2;
# | Запрос 1 | Запрос 2 |
---|---|---|
01 | 27.31с | |
02 | 27.18с | |
03 | 27.56с | |
04 | 27.14с | |
05 | 27.47с | |
06 | 27.47c | |
07 | 26.79c | |
08 | 26.95c | |
09 | 26.52c | |
10 | 28.06c |
$time_taken = microtime(true);
for($i = 0; $i < 10000; $i++)
{
mysql_query("Запрос");
}
$time_taken = microtime(true) - $time_taken;
DROP FUNCTION IF EXISTS `GET_SERVICE_STATE`;
DELIMITER //
CREATE FUNCTION `GET_SERVICE_STATE`(`services` BIGINT, `service` BIGINT)
RETURNS TINYINT
BEGIN
RETURN (`services` MOD (`service` * 4)) DIV `service`;
END //
DELIMITER ;
SELECT * FROM `test_a` WHERE GET_SERVICE_STATE(`services`, 64) = 2;
Works ~20 times slower than the original request. I can't figure out if it's because of the extra multiplication or because of the function call itself? Answer the question
In order to leave comments, you need to log in
I think your data structure is wrong.
I can suggest storing statuses in a separate table (cat_statuses).
+--------------------------------------+
| id | cat_id | status |
+--------------------------------------+
SELECT * FROM `cat_statuses` as cs
RIGHT JOIN `test_b` as tb ON (as.cat_id = tb.services)
WHERE cs.cat_id=4;
As far as I understand, you have objects that have many categories, which have many statuses.
I would divide this into 4 tables: objects, categories, statuses and a relationship table (object_id, category_id, status_id) - all 3 fields, by the way, can be combined into a composite primary key.
Because there are few statuses, you can take TINYINT as the primary key.
There is no need to make a 4-fold system - take pity on the brain of the one who will continue to support it.
Thus, you can easily make a request with joins for the necessary tables and everything will work very quickly.
Yes, and conducting speed tests based on 13,000 rows is not serious. Disable the mysql query cache (or simply SELECT SQL_NOCACHE <your query here> ) and make at least a million rows (so that the table does not fit into memory), then the results will be more interesting. Stored procedures by the way fulfill much more slowly than direct requests.
Read the book High Performance Mysql - it clears your brain a lot.
Let your table of objects have a field objectId - the identifier of the object. Let's create an additional table linked by the objectId field to the table of objects. The table contains the fields of the service number serviceNum and its serviceStatus.
CREATE TABLE `service_states`
`objectId` BIGINT NOT NULL DEFAULT '0',
`serviceNum` INT NOT NULL DEFAULT '0',
`serviceState` tinyint(1) DEFAULT '0',
PRIMARY KEY (`objectId`,`serviceNum`),
KEY `byServiceState` (`serviceState`),
KEY `byServiceNum` (`serviceNum`))
ENGINE=InnoDB DEFAULT CHARSET=utf8';
SELECT * FROM `test_b` as tb
RIGHT JOIN `service_states` as ss USING(objectId)
WHERE ss.serviceNum = 3 AND ss.serviceState = 2;
If you don't like the JOIN option so much, then try using the 10 number system (albeit a little redundant, but there will be a margin for statuses). The check will be reduced to the calculation of criteria on the PHP side:
$service = 3; // от 1 до 11
$status = 2; // от 1 до 4
$min = $status * pow(10, $service);
$max = ($status+1) * pow(10, $service);
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question