Funciones ocultas de MySQL

101

He estado trabajando con Microsoft SQL Server durante muchos años, pero recientemente comencé a usar MySQL con mis aplicaciones web, y tengo hambre de conocimiento.

Para continuar con la larga lista de preguntas sobre "funciones ocultas" , me gustaría conocer las funciones ocultas o útiles de MySQL que, con suerte, mejorarán mi conocimiento de esta base de datos de código abierto.

GateKiller
fuente

Respuestas:

161

Ya que ofreciste una recompensa, compartiré mis secretos ganados con tanto esfuerzo ...

En general, todos los SQL que sintonicé hoy requerían el uso de subconsultas. Habiendo venido del mundo de las bases de datos de Oracle, las cosas que daba por sentado no funcionaban igual con MySQL. Y mi lectura sobre el ajuste de MySQL me hace concluir que MySQL está detrás de Oracle en términos de optimización de consultas.

Si bien las consultas simples requeridas para la mayoría de las aplicaciones B2C pueden funcionar bien para MySQL, la mayoría de las consultas de informes agregados necesarias para Intelligence Reporting parecen requerir un poco de planificación y reorganización de las consultas SQL para guiar a MySQL a ejecutarlas más rápido.

Administración:

max_connectionses el número de conexiones simultáneas. El valor predeterminado es 100 conexiones (151 desde 5.0), muy pequeño.

Nota:

las conexiones ocupan memoria y es posible que su sistema operativo no pueda manejar muchas conexiones.

Los binarios de MySQL para Linux / x86 le permiten tener hasta 4096 conexiones concurrentes, pero los binarios autocompilados a menudo tienen un límite menor.

Configure table_cache para que coincida con el número de sus tablas abiertas y conexiones simultáneas. Observe el valor de open_tables y, si está creciendo rápidamente, deberá aumentar su tamaño.

Nota:

Los 2 parámetros anteriores pueden requerir muchos archivos abiertos. 20 + max_connections + table_cache * 2 es una buena estimación de lo que necesita. MySQL en Linux tiene una opción open_file_limit, establezca este límite.

Si tiene consultas complejas, es probable que sort_buffer_size y tmp_table_size sean muy importantes. Los valores dependerán de la complejidad de la consulta y los recursos disponibles, pero se recomiendan 4 Mb y 32 Mb, respectivamente, como puntos de partida.

Nota: Estos son valores "por conexión", entre read_buffer_size, read_rnd_buffer_size y algunos otros, lo que significa que este valor puede ser necesario para cada conexión. Por lo tanto, considere su carga y los recursos disponibles cuando configure estos parámetros. Por ejemplo, sort_buffer_size se asigna solo si MySQL necesita hacer una clasificación. Nota: tenga cuidado de no quedarse sin memoria.

Si tiene muchas conexiones establecidas (es decir, un sitio web sin conexiones persistentes), puede mejorar el rendimiento configurando thread_cache_size en un valor distinto de cero. 16 es un buen valor para empezar. Aumente el valor hasta que su threads_created no crezca muy rápidamente.

CLAVE PRIMARIA:

Solo puede haber una columna AUTO_INCREMENT por tabla, debe estar indexada y no puede tener un valor DEFAULT

CLAVE es normalmente un sinónimo de ÍNDICE. El atributo de clave PRIMARY KEY también se puede especificar como solo KEY cuando se proporciona en una definición de columna. Esto se implementó por compatibilidad con otros sistemas de bases de datos.

UNA CLAVE PRIMARIA es un índice único en el que todas las columnas de clave deben definirse como NO NULAS

Si un índice PRIMARY KEY o UNIQUE consta de una sola columna que tiene un tipo entero, también puede hacer referencia a la columna como "_rowid" en las sentencias SELECT.

En MySQL, el nombre de una PRIMARY KEY es PRIMARY

Actualmente, solo las tablas InnoDB (v5.1?) Admiten claves externas.

Por lo general, crea todos los índices que necesita cuando crea tablas. Se indexará cualquier columna declarada como PRIMARY KEY, KEY, UNIQUE o INDEX.

NULL significa "no tener un valor". Para probar NULL, no puede usar los operadores de comparación aritmética como =, <o <>. En su lugar, utilice los operadores IS NULL y IS NOT NULL:

NO_AUTO_VALUE_ON_ZERO suprime el incremento automático para 0 de modo que solo NULL genera el siguiente número de secuencia. Este modo puede resultar útil si se ha almacenado 0 en la columna AUTO_INCREMENT de una tabla. (Por cierto, almacenar 0 no es una práctica recomendada).

Para cambiar el valor del contador AUTO_INCREMENT que se utilizará para nuevas filas:

ALTER TABLE mytable AUTO_INCREMENT = value; 

o SET INSERT_ID = valor;

A menos que se especifique lo contrario, el valor comenzará con: 1000000 o especificarlo así:

...) ENGINE = MyISAM DEFAULT CHARSET = latin1 AUTO_INCREMENT = 1

HORARIOS:

Los valores de las columnas TIMESTAMP se convierten de la zona horaria actual a UTC para el almacenamiento y de UTC a la zona horaria actual para su recuperación.

http://dev.mysql.com/doc/refman/5.1/en/timestamp.html Para una columna TIMESTAMP en una tabla, puede asignar la marca de tiempo actual como el valor predeterminado y el valor de actualización automática.

Una cosa a tener en cuenta cuando se usa uno de estos tipos en una cláusula WHERE, es mejor hacer WHERE datecolumn = FROM_UNIXTIME (1057941242) y no WHERE UNIX_TIMESTAMP (datecolumn) = 1057941242. hacer esto último no aprovechará un índice en esa columna.

http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html

 UNIX_TIMESTAMP() 
 FROM_UNIXTIME() 
 UTC_DATE()
 UTC_TIME()
 UTC_TIMESTAMP()

si convierte una fecha y hora a una marca de tiempo unix en MySQL:
Y luego agregue 24 horas:
Y luego vuelva a convertirla en una fecha y hora, ¡mágicamente pierde una hora!

Esto es lo que está pasando. Al convertir la marca de tiempo de Unix a una fecha y hora, la zona horaria se toma en consideración y da la casualidad de que entre el 28 y el 29 de octubre de 2006 salimos del horario de verano y perdimos una hora.

A partir de MySQL 4.1.3, las funciones CURRENT_TIMESTAMP (), CURRENT_TIME (), CURRENT_DATE () y FROM_UNIXTIME () devuelven valores en la zona horaria actual de la conexión , que está disponible como el valor de la variable de sistema time_zone. Además, UNIX_TIMESTAMP () asume que su argumento es un valor de fecha y hora en la zona horaria actual.

La configuración de la zona horaria actual no afecta a los valores mostrados por funciones como UTC_TIMESTAMP () o valores en las columnas DATE, TIME o DATETIME.

NOTA: ON UPDATE ONLY actualiza la fecha y hora si se cambia un campo. Si una ACTUALIZACIÓN da como resultado que no se cambien los campos, la fecha y hora NO se actualiza.

Además, el primer TIMESTAMP siempre es AUTOUPDATE de forma predeterminada, incluso si no se especifica

Cuando trabajo con fechas, casi siempre me convierto en fecha juliana porque la matemática de datos es una simple cuestión de sumar o restar números enteros y segundos desde medianoche por la misma razón. Es raro que necesite una resolución de tiempo de granularidad más fina que segundos.

Ambos se pueden almacenar como un entero de 4 bytes, y si el espacio es realmente reducido se pueden combinar en el tiempo de UNIX (segundos desde la época 1/1/1970) como un entero sin signo que será válido hasta alrededor de 2106 como:

'segundos en 24 horas = 86400

'Signed Integer max val = 2,147,483,647 - puede contener 68 años de Segundos

'Entero sin signo max val = 4.294.967.295 - puede contener 136 años de Segundos

Protocolo binario:

MySQL 4.1 introdujo un protocolo binario que permite enviar y devolver valores de datos que no son cadenas en formato nativo sin conversión hacia y desde el formato de cadena. (Muy útil)

Aparte, mysql_real_query () es más rápido que mysql_query () porque no llama a strlen () para operar en la cadena de instrucciones.

http://dev.mysql.com/tech-resources/articles/4.1/prepared-statements.html El protocolo binario admite declaraciones preparadas del lado del servidor y permite la transmisión de valores de datos en formato nativo. El protocolo binario se sometió a bastante revisión durante las versiones anteriores de MySQL 4.1.

Puede utilizar la macro IS_NUM () para probar si un campo tiene un tipo numérico. Pase el valor del tipo a IS_NUM () y se evalúa como TRUE si el campo es numérico:

Una cosa a tener en cuenta es que los datos binarios PUEDEN enviarse dentro de una consulta normal si la escapas y recuerdas que MySQL solo requiere que la barra invertida y el carácter de comillas se escapen . Entonces, esa es una manera realmente fácil de INSERTAR cadenas binarias más cortas, como contraseñas cifradas / saladas, por ejemplo.

Servidor maestro:

http://www.experts-exchange.com/Database/MySQL/Q_22967482.html

http://www.databasejournal.com/features/mysql/article.php/10897_3355201_2

CONCESIÓN DE REPLICACIÓN ESCLAVO ENCENDIDO . a slave_user IDENTIFICADO POR 'slave_password'

#Master Binary Logging Config  STATEMENT causes replication 
              to be statement-based -  default

log-bin=Mike
binlog-format=STATEMENT
server-id=1            
max_binlog_size = 10M
expire_logs_days = 120    


#Slave Config
master-host=master-hostname
master-user=slave-user
master-password=slave-password
server-id=2

El archivo de registro binario debe leer:

http://dev.mysql.com/doc/refman/5.0/en/binary-log.html

http://www.mydigitallife.info/2007/10/06/how-to-read-mysql-binary-log-files-binlog-with-mysqlbinlog/

http://dev.mysql.com/doc/refman/5.1/en/mysqlbinlog.html

http://dev.mysql.com/doc/refman/5.0/en/binary-log.html

http://dev.mysql.com/doc/refman/5.1/en/binary-log-setting.html

Puede eliminar todos los archivos de registro binarios con la instrucción RESET MASTER, o un subconjunto de ellos con PURGE MASTER

--result-file = binlog.txt TrustedFriend-bin.000030

Normalización:

http://dev.mysql.com/tech-resources/articles/intro-to-normalization.html

Funciones UDF

http://www.koders.com/cpp/fid10666379322B54AD41AEB0E4100D87C8CDDF1D8C.aspx

http://souptonuts.sourceforge.net/readme_mysql.htm

Tipos de datos:

http://dev.mysql.com/doc/refman/5.1/en/storage-requirements.html

http://www.informit.com/articles/article.aspx?p=1238838&seqNum=2

http://bitfilm.net/2008/03/24/saving-bytes-efficient-data-storage-mysql-part-1/

Una cosa a tener en cuenta es que en una tabla mixta con CHAR y VARCHAR, mySQL cambiará los CHAR a VARCHAR

RecNum integer_type UNSIGNED NOT NULL AUTO_INCREMENT, PRIMARY KEY (RecNum)

MySQL siempre representa las fechas con el año primero, de acuerdo con las especificaciones estándar SQL e ISO 8601

Misc:

Desactivar algunas funciones de MySQl dará como resultado archivos de datos más pequeños y un acceso más rápido. Por ejemplo:

--datadir especificará el directorio de datos y

--skip-innodb desactivará la opción inno y te ahorrará entre 10 y 20 millones

Más aquí http://dev.mysql.com/tech-resources/articles/mysql-c-api.html

Descargar Capítulo 7 - Gratis

InnoDB es transaccional, pero conlleva una sobrecarga de rendimiento. He encontrado que las tablas MyISAM son suficientes para el 90% de mis proyectos. Las tablas no seguras para transacciones (MyISAM) tienen varias ventajas propias, todas las cuales ocurren porque:

no hay gastos generales de transacción:

Mucho mas rápido

Menores requisitos de espacio en disco

Se requiere menos memoria para realizar actualizaciones

Cada tabla MyISAM se almacena en el disco en tres archivos. Los archivos tienen nombres que comienzan con el nombre de la tabla y tienen una extensión para indicar el tipo de archivo. Un archivo .frm almacena el formato de la tabla. El archivo de datos tiene una extensión .MYD (MYData). El archivo de índice tiene una extensión .MYI (MYIndex).

Estos archivos se pueden copiar en una ubicación de almacenamiento intactos sin utilizar la función de copia de seguridad de administradores de MySQL, que consume mucho tiempo (también lo es la restauración)

El truco es hacer una copia de estos archivos y luego SUJETAR la mesa. Cuando vuelva a colocar los archivos, MySQl los reconocerá y actualizará el seguimiento de la tabla.

Si debe hacer una copia de seguridad / restaurar,

Restaurar una copia de seguridad o importar desde un archivo de volcado existente puede llevar mucho tiempo dependiendo de la cantidad de índices y claves primarias que tenga en cada tabla. Puede acelerar este proceso drásticamente modificando su archivo de volcado original rodeándolo con lo siguiente:

SET AUTOCOMMIT = 0;
SET FOREIGN_KEY_CHECKS=0;

.. your dump file ..

SET FOREIGN_KEY_CHECKS = 1;
COMMIT;
SET AUTOCOMMIT = 1;

Para aumentar enormemente la velocidad de recarga, agregue el comando SQL SET AUTOCOMMIT = 0; al principio del archivo de volcado y agregue COMMIT; comando hasta el final.

De forma predeterminada, la confirmación automática está activada, lo que significa que todos y cada uno de los comandos de inserción en el archivo de volcado se tratarán como una transacción separada y se escribirán en el disco antes de que se inicie el siguiente. Si no agrega estos comandos, volver a cargar una base de datos grande en InnoDB puede llevar muchas horas ...

El tamaño máximo de una fila en una tabla MySQL es 65,535 bytes

La longitud máxima efectiva de un VARCHAR en MySQL 5.0.3 y en = tamaño máximo de fila (65,535 bytes)

Los valores VARCHAR no se rellenan cuando se almacenan. Los espacios finales se conservan cuando los valores se almacenan y recuperan, de conformidad con SQL estándar.

Los valores CHAR y VARCHAR en MySQL se comparan sin tener en cuenta los espacios finales.

El uso de CHAR solo acelerará su acceso si todo el registro tiene un tamaño fijo. Es decir, si usa cualquier objeto de tamaño variable, también puede hacer que todos sean de tamaño variable. No gana velocidad al usar un CHAR en una tabla que también contiene un VARCHAR.

El límite de VARCHAR de 255 caracteres se elevó a 65535 caracteres a partir de MySQL 5.0.3

Las búsquedas de texto completo solo son compatibles con tablas MyISAM.

http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html

Las columnas BLOB no tienen juego de caracteres y la clasificación y la comparación se basan en los valores numéricos de los bytes en los valores de las columnas.

Si el modo SQL estricto no está habilitado y asigna un valor a una columna BLOB o TEXT que excede la longitud máxima de la columna, el valor se trunca para ajustarse y se genera una advertencia.

Comandos útiles:

comprobar el modo estricto: SELECT @@ global.sql_mode;

desactivar el modo estricto:

SET @@ global.sql_mode = '';

SET @@ global.sql_mode = 'MYSQL40'

o eliminar: sql-mode = "STRICT_TRANS_TABLES, ...

MOSTRAR COLUMNAS DE mytable

SELECCIONE max (namecount) COMO virtualcolumnDE mytable ORDENE POR virtualcolumn

http://dev.mysql.com/doc/refman/5.0/en/group-by-hidden-fields.html

http://dev.mysql.com/doc/refman/5.1/en/information-functions.html#function_last-insert-id last_insert_id ()

obtiene el PK de la última fila insertada en el hilo actual max (pkcolname) obtiene el último PK en general.

Nota: si la tabla está vacía, max (pkcolname) devuelve 1 mysql_insert_id () convierte el tipo de retorno de la función nativa de la API de MySQL C mysql_insert_id () a un tipo de largo (llamado int en PHP).

Si su columna AUTO_INCREMENT tiene un tipo de columna de BIGINT, el valor devuelto por mysql_insert_id () será incorrecto. En su lugar, utilice la función SQL interna de MySQL LAST_INSERT_ID () en una consulta SQL.

http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_last-insert-id

Solo una nota que cuando intentas insertar datos en una tabla y obtienes el error:

Unknown column the first bit of data what you want to put into the table in field list

usando algo como

INSERT INTO table (this, that) VALUES ($this, $that)

es porque no tiene apóstrofos alrededor de los valores que está tratando de incluir en la tabla. Entonces deberías cambiar tu código a:

INSERT INTO table (this, that) VALUES ('$this', '$that') 

recordatorio de que `` se utilizan para definir campos, bases de datos o tablas de MySQL, no valores;)

Conexión perdida al servidor durante la consulta:

http://dev.mysql.com/doc/refman/5.1/en/gone-away.html

http://dev.mysql.com/doc/refman/5.1/en/packet-too-large.html

http://dev.mysql.com/doc/refman/5.0/en/server-parameters.html

http://dev.mysql.com/doc/refman/5.1/en/show-variables.html

http://dev.mysql.com/doc/refman/5.1/en/option-files.html

http://dev.mysql.com/doc/refman/5.1/en/error-log.html

Consultas de ajuste

http://www.artfulsoftware.com/infotree/queries.php?&bw=1313

Bueno, creo que eso debería ser suficiente para ganar el bono ... Los frutos de muchas horas y muchos proyectos con una gran base de datos gratuita . Desarrollo servidores de datos de aplicaciones en plataformas Windows principalmente con MySQL. El peor lío que tuve que arreglar fue

La última pesadilla de base de datos heredada de MySQL

Esto requirió una serie de aplicaciones para procesar las tablas en algo útil usando muchos de los trucos mencionados aquí.

Si encontró esto sorprendentemente útil, exprese su agradecimiento votando hacia arriba.

Consulte también mis otros artículos y documentos técnicos en: www.coastrd.com

Mike Trader
fuente
22

Una de las características no tan ocultas de MySQL es que no es realmente bueno para ser compatible con SQL, bueno, en realidad no son errores, pero hay más trampas ... :-)

estera
fuente
Haciendo saber a otros que esta lista ha sido valiosa al pasar de MSSQL a MySQL. Saludos Mat.
GateKiller
Muchos de esos errores son de versiones anteriores de MySQL.
jmucchiello
por un lado, no creo que nunca sea posible poner un valor NULL en un campo de marca de tiempo.
mat
3
MySQL no es particularmente peor en ser compatible con SQL que muchas otras bases de datos; Siempre que se ciña a un subconjunto sano de SQL, generalmente puede evitar las trampas, que es más de lo que se puede decir, por ejemplo. Las infames cadenas vacías NULL de Oracle.
Bobince
1
Puede desactivar algunas de las trampasSET SESSION sql_mode='ANSI';
Kornel
21

Un comando para averiguar qué tablas están actualmente en la caché:

mysql> SHOW open TABLES FROM test;
+----------+-------+--------+-------------+
| DATABASE | TABLE | In_use | Name_locked |
+----------+-------+--------+-------------+
| test     | a     |      3 |           0 |
+----------+-------+--------+-------------+
1 row IN SET (0.00 sec)

(Del blog de rendimiento de MySQL )

Eran Galperin
fuente
15

Un comando para averiguar quién está haciendo qué:

mysql> show processlist;
show processlist;
+----+-------------+-----------------+------+---------+------+----------------------------------+------------------+
| Id | User        | Host            | db   | Command | Time | State                            | Info             |
+----+-------------+-----------------+------+---------+------+----------------------------------+------------------+
|  1 | root        | localhost:32893 | NULL | Sleep   |    0 |                                  | NULL             |
|  5 | system user |                 | NULL | Connect |   98 | Waiting for master to send event | NULL             |
|  6 | system user |                 | NULL | Connect | 5018 | Reading event from the relay log | NULL             |
+-----+------+-----------+---------+---------+-------+-------+------------------+
3 rows in set (0.00 sec) 

Y puede matar un proceso con:

mysql>kill 5 
CMS
fuente
5
también MOSTRAR LISTA DE PROCESOS COMPLETA si no desea que las consultas se trunquen.
Greg
11

En particular, me gusta el soporte integrado de MySQL para inet_ntoa()y inet_aton(). Hace que el manejo de direcciones IP en tablas sea muy sencillo (¡al menos siempre que sean solo direcciones IPv4!)

Alnitak
fuente
2
PostgreSQL tiene un tipo inet muy agradable, que maneja muy bien ipv4 e ipv6 :-)
mat
A mí también me gustaban, pero no tener que usarlos en absoluto es aún mejor. +1 para Postgres.
Kornel
11

Me encanta on duplicate key(AKA upsert, merge) para todo tipo de contadores creados de forma perezosa:

insert into occurances(word,count) values('foo',1),('bar',1) 
  on duplicate key cnt=cnt+1

Puede insertar muchas filas en una consulta y manejar inmediatamente el índice duplicado para cada una de las filas.

porneL
fuente
10

Nuevamente, no características realmente ocultas, pero sí muy útiles:

Característica

Agarre fácilmente DDL:

SHOW CREATE TABLE CountryLanguage

salida:

CountryLanguage | CREATE TABLE countrylanguage (
  CountryCode char(3) NOT NULL DEFAULT '',
  Language char(30) NOT NULL DEFAULT '',
  IsOfficial enum('T','F') NOT NULL DEFAULT 'F',
  Percentage float(4,1) NOT NULL DEFAULT '0.0',
  PRIMARY KEY (CountryCode,Language)
) ENGINE=MyISAM DEFAULT CHARSET=latin1

Característica: función agregada GROUP_CONCAT () Crea una cadena concatenada de sus argumentos por detalle, y los agrega concatenando aquellos por grupo.

Ejemplo 1: simple

SELECT   CountryCode
,        GROUP_CONCAT(Language) AS List
FROM     CountryLanguage
GROUP BY CountryCode             

Salida:

+-------------+------------------------------------+
| CountryCode | List                               |
+-------------+------------------------------------+
| ABW         | Dutch,English,Papiamento,Spanish   |
. ...         . ...                                .
| ZWE         | English,Ndebele,Nyanja,Shona       |
+-------------+------------------------------------+

Ejemplo 2: múltiples argumentos

SELECT   CountryCode
,        GROUP_CONCAT(
             Language
,            IF(IsOfficial='T', ' (Official)', '')
         )               AS List
FROM     CountryLanguage
GROUP BY CountryCode

Salida:

+-------------+---------------------------------------------+
| CountryCode | List                                        |
+-------------+---------------------------------------------+
| ABW         | Dutch (Official),English,Papiamento,Spanish |
. ...         . ...                                         .
| ZWE         | English (Official),Ndebele,Nyanja,Shona     |
+-------------+---------------------------------------------+

Ejemplo 3: uso de un separador personalizado

SELECT   CountryCode
,        GROUP_CONCAT(Language SEPARATOR ' and ') AS List
FROM     CountryLanguage
GROUP BY CountryCode

Salida:

+-------------+----------------------------------------------+
| CountryCode | List                                         |
+-------------+----------------------------------------------+
| ABW         | Dutch and English and Papiamento and Spanish |
. ...         . ...                                          .
| ZWE         | English and Ndebele and Nyanja and Shona     |
+-------------+----------------------------------------------+

Ejemplo 4: controlar el orden de los elementos de la lista

SELECT   CountryCode
,        GROUP_CONCAT(
         Language
         ORDER BY CASE IsOfficial WHEN 'T' THEN 1 ELSE 2 END DESC
         ,        Language
         )               AS List
FROM     CountryLanguage
GROUP BY CountryCode

Salida:

+-------------+------------------------------------+
| CountryCode | List                               |
+-------------+------------------------------------+
| ABW         | English,Papiamento,Spanish,Dutch,  |
. ...         . ...                                .
| ZWE         | Ndebele,Nyanja,Shona,English       |
+-------------+------------------------------------+

Característica: COUNT (DISTINCT) con múltiples expresiones

Puede utilizar varias expresiones en una expresión COUNT (DISTINCT ...) para contar el número de combinaciones.

SELECT COUNT(DISTINCT CountryCode, Language) FROM CountryLanguage

Característica / Gotcha: No es necesario incluir expresiones no agregadas en la lista GROUP BY

La mayoría de RDBMS-es imponen un GROUP BY compatible con SQL92 que requiere que todas las expresiones no agregadas en la lista SELECT aparezcan en GROUP BY. En estos RDBMS-es, esta declaración:

SELECT     Country.Code, Country.Continent, COUNT(CountryLanguage.Language)
FROM       CountryLanguage 
INNER JOIN Country 
ON         CountryLanguage.CountryCode = Country.Code
GROUP BY   Country.Code

no es válido, porque la lista SELECT contiene la columna no agregada Country.Continent que no aparece en la lista GROUP BY. En estos RDBMS-es, debe modificar la lista GROUP BY para leer

GROUP BY   Country.Code, Country.Continent

o debe agregar algún agregado sin sentido a Country.Continent, por ejemplo

SELECT     Country.Code, MAX(Country.Continent), COUNT(CountryLanguage.Language)

Ahora bien, es que lógicamente no hay nada que exija que País.Continente se agregue. Consulte, Country.Code es la clave principal de la tabla Country. Country.Continent también es una columna de la tabla Country y, por lo tanto, por definiciones depende funcionalmente de la clave principal Country.Code. Por lo tanto, debe existir exactamente un valor en Country.Continent para cada Country.Code distinto. Si te das cuenta de eso, entonces te das cuenta de que no tiene sentido agregarlo (solo hay un valor, correcto) ni agrupar por él (ya que no hará que el resultado sea más único ya que ya estás agrupando por el pk)

De todos modos, MySQL le permite incluir columnas no agregadas en la lista SELECT sin necesidad de que las agregue también a la cláusula GROUP BY.

El problema con esto es que MySQL no lo protege en caso de que use una columna no agregada. Entonces, una consulta como esta:

SELECT     Country.Code, COUNT(CountryLanguage.Language), CountryLanguage.Percentage
FROM       CountryLanguage 
INNER JOIN Country 
ON         CountryLanguage.CountryCode = Country.Code
GROUP BY   Country.Code

Se ejecutará sin quejas, pero la columna CountryLanguage.Percentage contendrá porcentajes sin sentido (es decir, de todos los porcentajes de idiomas, uno de los valores disponibles para el porcentaje se elegirá al azar o al menos fuera de tu control.

Ver: Grupo de desacreditación por mitos

anon
fuente
Permitir columnas no declaradas en grupo por es una de mis características menos favoritas provenientes de Oracle. Es un gran problema si está acostumbrado a Oracle: simplemente le permite ejecutar la consulta, los resultados se ven bien, pero luego se da cuenta de que no está haciendo lo que pensaba que estaba haciendo.
mbafford
7

El comando "pager" en el cliente

Si tiene, digamos, 10,000 filas en su resultado y desea verlas (esto asume los comandos "less" y "tee" disponibles, que normalmente es el caso en Linux; en Windows YMMV).

pager less
select lots_of_stuff FROM tbl WHERE clause_which_matches_10k_rows;

Y los obtendrá en el visor de archivos "menos" para que pueda hojearlos, buscar, etc.

también

pager tee myfile.txt
select a_few_things FROM tbl WHERE i_want_to_save_output_to_a_file;

Escribirá cómodamente en un archivo.

MarkR
fuente
desafortunadamente en Windows, incluso si existen "less" y "tee", la opción de buscapersonas en sí no es compatible. no fácilmente de todos modos
Berry Tsakala
6

Algunas cosas que pueden resultarle interesantes:

<query>\G -- \G in the CLI instead of the ; will show one column per row
explain <query>; -- this will show the execution plan for the query
SorinV
fuente
3

Estos son algunos de mis consejos: escribí sobre ellos en mi blog ( Enlace )

  1. No es necesario utilizar el signo '@' al declarar variables.
  2. Debe usar un delimitador (el predeterminado es ';') para demarcar el final de una declaración - Enlace
  3. Si intenta mover datos entre MS-SQL 2005 y mySQL, hay algunos obstáculos que debe superar: Enlace
  4. Haciendo coincidencias sensibles a mayúsculas y minúsculas en mySQL - enlace
Nikhil
fuente
3

Si va a trabajar con bases de datos InnoDb de transacciones grandes y / o de alto volumen, aprenda y comprenda el blog de rendimiento de Mysql "MOSTRAR ESTADO DE INNODB" , se convertirá en su amigo.

Hawk Kroeger
fuente
3

Si usa cmdline Mysq, puede interactuar con la línea de comandos (en máquinas Linux, no estoy seguro de si hay un efecto equivalente en Windows) usando el grito / signo de exclamación. Por ejemplo:

\! cat file1.sql

mostrará el código para file1.sql. Para guardar su declaración y consulta en un archivo, use la función de tee

\T filename

para apagar esto use \ t

Por último, para ejecutar un script que ya ha guardado, utilice "nombre de archivo de origen". Por supuesto, la alternativa normal es dirigir el nombre del script al iniciar mysql desde la línea de comando:

    mysql -u root -p < case1.sql

¡Espero que sea de utilidad para alguien!

Editar: Acabo de recordar otro: al invocar mysql desde la línea de comando, puede usar el modificador -t para que la salida esté en formato de tabla, una verdadera bendición con algunas consultas (aunque, por supuesto, terminar las consultas con \ G como se menciona en otra parte aquí también es útil a este respecto). Mucho más sobre varios conmutadores Herramienta de línea de comandos

Acabo de descubrir una forma sencilla de cambiar el orden de una clasificación (normalmente use Case ...) Si desea cambiar el orden de una clasificación (tal vez ordenar por 1, 4, 3, 2 en lugar de 1, 2, 3, 4) puede utilizar la función de campo dentro de la cláusula Order by. Por ejemplo

Ordenar por campo (sort_field, 1,4,3,2)

DBMarcos99
fuente
3

No creo que esto sea específico de MySQL, pero me ilumina:

En lugar de escribir

WHERE (x.id > y.id) OR (x.id = y.id AND x.f2 > y.f2) 

Puedes escribir

WHERE (x.id, x.f2) > (y.id, y.f2)
Johan
fuente
Eso es realmente genial, pero ¿cuáles serían algunos casos de uso para esto?
mangoDrunk
Podría ser útil para encontrar todos los registros que sean más grandes que un registro determinado.
Fantius
2

mysqlsla: una de las herramientas de análisis de registro de consultas lentas más utilizadas. Puede ver las 10 consultas de preocupaciones principales desde la última vez que lanzó registros de consultas lentas. También puede indicarle la cantidad de veces que se disparó una consulta MALA y cuánto tiempo total tardó en el servidor.

pawan
fuente
2

Realmente documentado , pero muy molesto: conversiones automáticas para fechas incorrectas y otras entradas incorrectas.

Antes de MySQL 5.0.2, MySQL perdona valores de datos ilegales o incorrectos y los obliga a valores legales para la entrada de datos. En MySQL 5.0.2 y versiones posteriores, ese sigue siendo el comportamiento predeterminado, pero puede cambiar el modo SQL del servidor para seleccionar un tratamiento más tradicional de valores incorrectos, de modo que el servidor los rechace y anule la declaración en la que ocurren.

En cuanto a las fechas: a veces tendrás "suerte" cuando MySQL no ajusta la entrada a fechas válidas cercanas, sino que la almacena como, 0000-00-00por definición, no válida. Sin embargo, incluso entonces, es posible que desee que MySQL falle en lugar de almacenar silenciosamente este valor.

Arjan
fuente
1

InnoDB por defecto almacena todas las tablas en un espacio de tabla global que nunca se encogerá .

Puedes usar innodb_file_per_table que colocará cada tabla en un espacio de tabla separado que se eliminará cuando suelte la tabla o la base de datos.

Planifique esto con anticipación, ya que debe volcar y restaurar la base de datos para recuperar espacio de lo contrario.

Uso de espacios de tabla por tabla

serbaut
fuente
1

Si inserta en la columna de fecha y hora el valor de cadena vacía "", MySQL retendrá el valor como 00/00/0000 00:00:00. A diferencia de Oracle, que ahorrará valor nulo.

Devid G
fuente
1

Durante mis evaluaciones comparativas con grandes conjuntos de datos y campos DATETIME, siempre es más lento hacer esta consulta:

SELECT * FROM mytable
WHERE date(date_colum) BETWEEN '2011-01-01' AND ''2011-03-03';

Que este enfoque:

SELECT * FROM mytable
WHERE date_column BETWEEN '2011-01-01 00:00:00' AND '2011-03-03 23:59:59'
Osvaldo Mercado
fuente