2025-04-14

方法1

将downloads目录下面的reviews.csv插入到reviews表. 并忽略第一行. 以\r\n为换行

LOAD DATA LOCAL INFILE
'Users/xiukun/Downloads/reviews.csv'INTO TABLE steam reviews
FIELDS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY "\r\n"
IGNORE 1 LINES
(afield, bfield, cfield)

 

方法2

使用mysqlimport

mysqlimport --ignore-lines=1 \
            --fields-terminated-by=, \
            --local -u root \
            -p Database \
             TableName.csv
 

 

标签: mysql
2025-04-14

1.增加索引到自定义Entity

下面我们来使用代码定义一个entity.

下面定义了一个Request的Entity: mymodule/src/Entity/Request.php

<?php

namespace Drupal\mymodule\Entity;

use Drupal\Core\Entity\ContentEntityBase;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition;

/**
 *
 * @ContentEntityType(
 *   id = "requests",
 *   label = @Translation("Requests"),
 *   handlers = {
 *     "view_builder" = "Drupal\Core\Entity\EntityViewBuilder",
 *     "list_builder" = "Drupal\Core\Entity\EntityListBuilder",
 *     "views_data" = "Drupal\views\EntityViewsData",
 *     "form" = {
 *       "default" = "Drupal\Core\Entity\ContentEntityForm",
 *       "add" = "Drupal\Core\Entity\ContentEntityForm",
 *       "edit" = "Drupal\Core\Entity\ContentEntityForm",
 *       "delete" = "Drupal\Core\Entity\ContentEntityDeleteForm",
 *     },
 *     "route_provider" = {
 *       "html" = "Drupal\Core\Entity\Routing\AdminHtmlRouteProvider",
 *     },
 *     "access" = "Drupal\Core\Entity\EntityAccessControlHandler",
 *   },
 *   admin_permission = "administer requests",
 *   base_table = "requests",
 *   translatable = FALSE,
 *   entity_keys = {
 *     "id" = "id",
 *     "uuid" = "uuid"
 *   },
 * )
 */
class Requests extends ContentEntityBase {

  /**
   * {@inheritdoc}
   */
  public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
    $fields = parent::baseFieldDefinitions($entity_type);

    $fields['method'] = BaseFieldDefinition::create('string')
      ->setLabel(t('method'));

    $fields['url'] = BaseFieldDefinition::create('string')
      ->setLabel(t('url'));


    return $fields;
  }

}

 

添加4条数据作为测试

$storage = \Drupal::entityTypeManager()->getStorage('requests');
$storage->create([
    'method' => 'POST',
    'url' => 'https://www.a.com'
  ])->save();

$storage->create([
    'method' => 'GET',
    'url' => 'https://www.b.com'
  ])->save();

$storage->create([
    'method' => 'PUT',
    'url' => 'https://www.c.com'
  ])->save();

$storage->create([
    'method' => 'DELETE',
    'url' => 'https://www.d.com'
  ])->save();

 

打开PHPMyAdmin查看会看到有4条数据.

 

现在执行一个自定义SQL查询数据

SELECT * FROM `requests` WHERE method="POST"

这里会很正常的显示一条.

然后我们这边使用EXPLAIN来查看SQL查询细节

我们会发现我们想要的其实是其中一条数据. 但是SELECT他进行了全表扫描. 

其主要原因是因为我没有对字段增加索引, 如果你要对表进行搜索你必须对其增加索引. 不增加就会全表扫描.

我们需要修改一下entity定义. 增加一个storage_schema

 *   handlers = {
 *     "view_builder" = "Drupal\Core\Entity\EntityViewBuilder",
 *     "list_builder" = "Drupal\Core\Entity\EntityListBuilder",
 *     "storage_schema" = "Drupal\mymodule\RequestsStorageSchema",

接着我们定义 mymodule/src/RequestsStorageSchema.php

<?php
namespace Drupal\mymodule;

use Drupal\Core\Entity\ContentEntityTypeInterface;
use Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema;

/**
 * Defines the Requests schema handler.
 */
class RequestsStorageSchema extends SqlContentEntityStorageSchema {
  /**
   * {@inheritdoc}
   */
  protected function getEntitySchema(ContentEntityTypeInterface $entity_type, $reset = FALSE) {
    $schema = parent::getEntitySchema($entity_type, $reset);
    if ($data_table = $this->storage->getBaseTable()) {
      $schema[$data_table]['indexes'] += [
        'requests__url' => ['url'],
        'requests__method' => ['method'],
      ];
    }

    return $schema;
  }
}

接着我们只运行:  drush entity-updates, 此功能: https://www.drupal.org/project/devel_entity_updates

我们再运行上面的sql进行测试:

EXPLAIN SELECT * FROM `requests` WHERE method="POST"

这时候可以看到这里的rows已经变成了1

 

2.对Node Body字段和自定义字段增加索引

在系统的Node中. 我们经常需要对body也进行搜索. 但是body字段并没有索引所以就可能导致当文章很多的时候搜索会很漫.

自定义字段也是一样. 不会有索引. 我会在后台创建一个field_myname的字段

我们查询1条数据. 实际上他也是进行了全表扫描.

 

这里直接使用hook_entity_field_storage_info_alter

 
function mymodule_entity_field_storage_info_alter(&$fields, \Drupal\Core\Entity\EntityTypeInterface $entity_type) {
  if ($entity_type->id() == 'node' && !empty($fields['body'])) {
    $fields['body']->setIndexes(['value' => ['value']]);
    $fields['field_myname']->setIndexes(['value' => ['value']]);
  }
}

 

然后运行drush entity-updates 

接着测试sql

暂时没有模块可以提供可以增加索引的功能. 有一个field_index的模块但是并不支持drupal10, 还有一个模块可以提示views中搜索字段没有增加索引views_index_hint

 

标签: Drupal mysql
2025-04-14

首先定义一个事件服务.

mymodule.services.yml

services
  mymodule.event_subscriber:
    class: Drupal\mymodule\EventSubscriber\MariadbProfileSubscriber
    tags:
      - { name: event_subscriber }

定义服务内容

<?php
declare(strict_types=1);
namespace Drupal\mymodule\EventSubscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
/**
 * @todo Add description for this subscriber.
 */
final class MariadbProfileSubscriber implements EventSubscriberInterface {
  /**
   * Kernel request event handler.
   */
  public function onKernelRequest(RequestEvent $event): void {
    // 开启profiles
    \Drupal::database()->query('set profiling=1')->execute();
  }
  public function onResponse(ResponseEvent $event):void {
    if ($event->isMainRequest()) {
      $is_debug_more = true;
      $strings = '';
      // 通过show profiles查看页面所有query的相应速度.
      $query_list = \Drupal::database()->query('show profiles;')->fetchAll();
      uasort($query_list, function($a, $b) {
        return ($a->Duration < $b->Duration) ? 1 : -1;
      });
      foreach ($query_list as $item) {
        $strings .= <<<EOF
QueryID = {$item->Query_ID}
Query = {$item->Query}
Duration = {$item->Duration}
EOF;
        if ($is_debug_more) {
          // 通过select INFORMATION_SCHEMA.PROFILING表来查看单条sql为什么会漫.
          // 设置query id.
          \Drupal::database()->query('set @query_id=' . $item->Query_ID);
          $query = <<<EOF
  SELECT STATE, SUM(DURATION) AS Total_R,
      ROUND(
      100* SUM(DURATION)/
      (SELECT SUM(DURATION) FROM INFORMATION_SCHEMA.PROFILING WHERE QUERY_ID = @query_id), 2) AS Pct_R,
      COUNT(*) AS Calls,
      SUM(DURATION)/COUNT(*) AS "R/Ca11"
  FROM INFORMATION_SCHEMA.PROFILING
    WHERE QUERY_ID = @query_id
    GROUP BY STATE
    ORDER BY Total_R DESC;
  EOF;
          $res = \Drupal::database()->query($query)->fetchAll();
          foreach ($res as $sub_item) {
            $sub_item = (array)$sub_item;
            $strings .= <<<EOF
  STATE:{$sub_item["STATE"]}, Total_R:{$sub_item["Total_R"]}, Pct_R:{$sub_item["Pct_R"]}, Calls:{$sub_item["Calls"]}, R/Ca11:{$sub_item['R/Ca11']}
  EOF;
            $strings .= "\r\n";
          }
        }
        $strings .= "\r\n\r\n";
      }
      \Drupal::logger('debug_sql')->notice("<pre>{$strings}</pre>");
    }
  }
  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents(): array {
    return [
      KernelEvents::REQUEST => ['onKernelRequest'],
      KernelEvents::RESPONSE => ['onResponse']
    ];
  }
}

标签: Drupal mysql
2025-04-14

Qoueries  所有Query的数
Threads connected  已连接的线程
Threads running  正在运行的线程

$ mysqladmin ext -i1 | awk '/Qoueries/{q=$4-qp;qp=$4} /Threads_connected/{tc=$4} /Threads_running/{printf "%5d %5d %5d\n", q,tc, $4}'
标签: mysql
2025-04-14
mysql> create table mytable like oritable;   #将原表复制一份成新表mytable
mysql> alter table mytable engine=InnoDB;  #将新表的引擎修改成innodb
mysql> inset into mytable select * from oritable  #将原数据插入到新表中

当数据量大的j时候可以增加事物回滚.

START TRANSACTION;
mysql> inset into mytable select * from oritable  #将原数据插入到新表中
COMMIT;
标签: mysql